Changeset 375b458 for src


Ignore:
Timestamp:
Jul 23, 2009, 1:53:01 PM (15 years ago)
Author:
Frederik Heber <heber@…>
Branches:
Action_Thermostats, Add_AtomRandomPerturbation, Add_FitFragmentPartialChargesAction, Add_RotateAroundBondAction, Add_SelectAtomByNameAction, Added_ParseSaveFragmentResults, AddingActions_SaveParseParticleParameters, Adding_Graph_to_ChangeBondActions, Adding_MD_integration_tests, Adding_ParticleName_to_Atom, Adding_StructOpt_integration_tests, AtomFragments, Automaking_mpqc_open, AutomationFragmentation_failures, Candidate_v1.5.4, Candidate_v1.6.0, Candidate_v1.6.1, ChangeBugEmailaddress, ChangingTestPorts, ChemicalSpaceEvaluator, CombiningParticlePotentialParsing, Combining_Subpackages, Debian_Package_split, Debian_package_split_molecuildergui_only, Disabling_MemDebug, Docu_Python_wait, EmpiricalPotential_contain_HomologyGraph, EmpiricalPotential_contain_HomologyGraph_documentation, Enable_parallel_make_install, Enhance_userguide, Enhanced_StructuralOptimization, Enhanced_StructuralOptimization_continued, Example_ManyWaysToTranslateAtom, Exclude_Hydrogens_annealWithBondGraph, FitPartialCharges_GlobalError, Fix_BoundInBox_CenterInBox_MoleculeActions, Fix_ChargeSampling_PBC, Fix_ChronosMutex, Fix_FitPartialCharges, Fix_FitPotential_needs_atomicnumbers, Fix_ForceAnnealing, Fix_IndependentFragmentGrids, Fix_ParseParticles, Fix_ParseParticles_split_forward_backward_Actions, Fix_PopActions, Fix_QtFragmentList_sorted_selection, Fix_Restrictedkeyset_FragmentMolecule, Fix_StatusMsg, Fix_StepWorldTime_single_argument, Fix_Verbose_Codepatterns, Fix_fitting_potentials, Fixes, ForceAnnealing_goodresults, ForceAnnealing_oldresults, ForceAnnealing_tocheck, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_continued, ForceAnnealing_with_BondGraph_continued_betteresults, ForceAnnealing_with_BondGraph_contraction-expansion, FragmentAction_writes_AtomFragments, FragmentMolecule_checks_bonddegrees, GeometryObjects, Gui_Fixes, Gui_displays_atomic_force_velocity, ImplicitCharges, IndependentFragmentGrids, IndependentFragmentGrids_IndividualZeroInstances, IndependentFragmentGrids_IntegrationTest, IndependentFragmentGrids_Sole_NN_Calculation, JobMarket_RobustOnKillsSegFaults, JobMarket_StableWorkerPool, JobMarket_unresolvable_hostname_fix, MoreRobust_FragmentAutomation, ODR_violation_mpqc_open, PartialCharges_OrthogonalSummation, PdbParser_setsAtomName, PythonUI_with_named_parameters, QtGui_reactivate_TimeChanged_changes, Recreated_GuiChecks, Rewrite_FitPartialCharges, RotateToPrincipalAxisSystem_UndoRedo, SaturateAtoms_findBestMatching, SaturateAtoms_singleDegree, StoppableMakroAction, Subpackage_CodePatterns, Subpackage_JobMarket, Subpackage_LinearAlgebra, Subpackage_levmar, Subpackage_mpqc_open, Subpackage_vmg, Switchable_LogView, ThirdParty_MPQC_rebuilt_buildsystem, TrajectoryDependenant_MaxOrder, TremoloParser_IncreasedPrecision, TremoloParser_MultipleTimesteps, TremoloParser_setsAtomName, Ubuntu_1604_changes, stable
Children:
51c910
Parents:
a5b2c3a
Message:

fixed indentation from tabs to two spaces.

Location:
src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/builder.cpp

    ra5b2c3a r375b458  
    1515 * \section about About the Program
    1616 *
    17  *      Molecuilder is a short program, written in C++, that enables the construction of a coordinate set for the
    18  *      atoms making up an molecule by the successive statement of binding angles and distances and referencing to
    19  *      already constructed atoms.
     17 *  Molecuilder is a short program, written in C++, that enables the construction of a coordinate set for the
     18 *  atoms making up an molecule by the successive statement of binding angles and distances and referencing to
     19 *  already constructed atoms.
    2020 *
    21  *      A configuration file may be written that is compatible to the format used by PCP - a parallel Car-Parrinello
    22  *      molecular dynamics implementation.
     21 *  A configuration file may be written that is compatible to the format used by PCP - a parallel Car-Parrinello
     22 *  molecular dynamics implementation.
    2323 *
    2424 * \section install Installation
    2525 *
    26  *      Installation should without problems succeed as follows:
    27  *      -# ./configure (or: mkdir build;mkdir run;cd build; ../configure --bindir=../run)
    28  *      -# make
    29  *      -# make install
     26 *  Installation should without problems succeed as follows:
     27 *  -# ./configure (or: mkdir build;mkdir run;cd build; ../configure --bindir=../run)
     28 *  -# make
     29 *  -# make install
    3030 *
    31  *      Further useful commands are
    32  *      -# make clean uninstall: deletes .o-files and removes executable from the given binary directory\n
    33  *      -# make doxygen-doc: Creates these html pages out of the documented source
     31 *  Further useful commands are
     32 *  -# make clean uninstall: deletes .o-files and removes executable from the given binary directory\n
     33 *  -# make doxygen-doc: Creates these html pages out of the documented source
    3434 *
    3535 * \section run Running
    3636 *
    37  *      The program can be executed by running: ./molecuilder
     37 *  The program can be executed by running: ./molecuilder
    3838 *
    39  *      Note, that it uses a database, called "elements.db", in the executable's directory. If the file is not found,
    40  *      it is created and any given data on elements of the periodic table will be stored therein and re-used on
    41  *      later re-execution.
     39 *  Note, that it uses a database, called "elements.db", in the executable's directory. If the file is not found,
     40 *  it is created and any given data on elements of the periodic table will be stored therein and re-used on
     41 *  later re-execution.
    4242 *
    4343 * \section ref References
    4444 *
    45  *      For the special configuration file format, see the documentation of pcp.
     45 *  For the special configuration file format, see the documentation of pcp.
    4646 *
    4747 */
     
    6363static void AddAtoms(periodentafel *periode, molecule *mol)
    6464{
    65         atom *first, *second, *third, *fourth;
    66         Vector **atoms;
    67         Vector x,y,z,n; // coordinates for absolute point in cell volume
    68         double a,b,c;
    69         char choice;    // menu choice char
    70         bool valid;
    71 
    72         cout << Verbose(0) << "===========ADD ATOM============================" << endl;
    73         cout << Verbose(0) << " a - state absolute coordinates of atom" << endl;
    74         cout << Verbose(0) << " b - state relative coordinates of atom wrt to reference point" << endl;
    75         cout << Verbose(0) << " c - state relative coordinates of atom wrt to already placed atom" << endl;
    76         cout << Verbose(0) << " d - state two atoms, two angles and a distance" << endl;
    77         cout << Verbose(0) << " e - least square distance position to a set of atoms" << endl;
    78         cout << Verbose(0) << "all else - go back" << endl;
    79         cout << Verbose(0) << "===============================================" << endl;
    80         cout << Verbose(0) << "Note: Specifiy angles in degrees not multiples of Pi!" << endl;
    81         cout << Verbose(0) << "INPUT: ";
    82         cin >> choice;
    83 
    84         switch (choice) {
     65  atom *first, *second, *third, *fourth;
     66  Vector **atoms;
     67  Vector x,y,z,n;  // coordinates for absolute point in cell volume
     68  double a,b,c;
     69  char choice;  // menu choice char
     70  bool valid;
     71
     72  cout << Verbose(0) << "===========ADD ATOM============================" << endl;
     73  cout << Verbose(0) << " a - state absolute coordinates of atom" << endl;
     74  cout << Verbose(0) << " b - state relative coordinates of atom wrt to reference point" << endl;
     75  cout << Verbose(0) << " c - state relative coordinates of atom wrt to already placed atom" << endl;
     76  cout << Verbose(0) << " d - state two atoms, two angles and a distance" << endl;
     77  cout << Verbose(0) << " e - least square distance position to a set of atoms" << endl;
     78  cout << Verbose(0) << "all else - go back" << endl;
     79  cout << Verbose(0) << "===============================================" << endl;
     80  cout << Verbose(0) << "Note: Specifiy angles in degrees not multiples of Pi!" << endl;
     81  cout << Verbose(0) << "INPUT: ";
     82  cin >> choice;
     83
     84  switch (choice) {
    8585    default:
    8686      cout << Verbose(0) << "Not a valid choice." << endl;
    8787      break;
    88                         case 'a': // absolute coordinates of atom
     88      case 'a': // absolute coordinates of atom
    8989        cout << Verbose(0) << "Enter absolute coordinates." << endl;
    9090        first = new atom;
    9191        first->x.AskPosition(mol->cell_size, false);
    92         first->type = periode->AskElement();    // give type
    93         mol->AddAtom(first);    // add to molecule
    94                                 break;
    95 
    96                         case 'b': // relative coordinates of atom wrt to reference point
     92        first->type = periode->AskElement();  // give type
     93        mol->AddAtom(first);  // add to molecule
     94        break;
     95
     96      case 'b': // relative coordinates of atom wrt to reference point
    9797        first = new atom;
    9898        valid = true;
     
    106106          cout << Verbose(0) << "\n";
    107107        } while (!(valid = mol->CheckBounds((const Vector *)&first->x)));
    108         first->type = periode->AskElement();    // give type
    109         mol->AddAtom(first);    // add to molecule
    110                                 break;
    111 
    112                         case 'c': // relative coordinates of atom wrt to already placed atom
     108        first->type = periode->AskElement();  // give type
     109        mol->AddAtom(first);  // add to molecule
     110        break;
     111
     112      case 'c': // relative coordinates of atom wrt to already placed atom
    113113        first = new atom;
    114114        valid = true;
     
    122122          }
    123123        } while (!(valid = mol->CheckBounds((const Vector *)&first->x)));
    124         first->type = periode->AskElement();    // give type
    125         mol->AddAtom(first);    // add to molecule
     124        first->type = periode->AskElement();  // give type
     125        mol->AddAtom(first);  // add to molecule
    126126        break;
    127127
     
    224224          cout << Verbose(0) << endl;
    225225        } while (!(valid = mol->CheckBounds((const Vector *)&first->x)));
    226         first->type = periode->AskElement();    // give type
    227         mol->AddAtom(first);    // add to molecule
    228                                 break;
    229 
    230                         case 'e': // least square distance position to a set of atoms
     226        first->type = periode->AskElement();  // give type
     227        mol->AddAtom(first);  // add to molecule
     228        break;
     229
     230      case 'e': // least square distance position to a set of atoms
    231231        first = new atom;
    232232        atoms = new (Vector*[128]);
     
    248248
    249249          first->x.Output((ofstream *)&cout);
    250           first->type = periode->AskElement();  // give type
    251           mol->AddAtom(first);  // add to molecule
     250          first->type = periode->AskElement();  // give type
     251          mol->AddAtom(first);  // add to molecule
    252252        } else {
    253253          delete first;
    254254          cout << Verbose(0) << "Please enter at least two vectors!\n";
    255255        }
    256                                 break;
    257         };
     256        break;
     257  };
    258258};
    259259
     
    263263static void CenterAtoms(molecule *mol)
    264264{
    265         Vector x, y, helper;
    266         char choice;    // menu choice char
    267 
    268         cout << Verbose(0) << "===========CENTER ATOMS=========================" << endl;
    269         cout << Verbose(0) << " a - on origin" << endl;
    270         cout << Verbose(0) << " b - on center of gravity" << endl;
    271         cout << Verbose(0) << " c - within box with additional boundary" << endl;
    272         cout << Verbose(0) << " d - within given simulation box" << endl;
    273         cout << Verbose(0) << "all else - go back" << endl;
    274         cout << Verbose(0) << "===============================================" << endl;
    275         cout << Verbose(0) << "INPUT: ";
    276         cin >> choice;
    277 
    278         switch (choice) {
    279                 default:
    280                         cout << Verbose(0) << "Not a valid choice." << endl;
    281                         break;
    282                 case 'a':
    283                         cout << Verbose(0) << "Centering atoms in config file on origin." << endl;
    284                         mol->CenterOrigin((ofstream *)&cout, &x);
    285                         break;
    286                 case 'b':
    287                         cout << Verbose(0) << "Centering atoms in config file on center of gravity." << endl;
    288                         mol->CenterGravity((ofstream *)&cout, &x);
    289                         break;
    290                 case 'c':
    291                         cout << Verbose(0) << "Centering atoms in config file within given additional boundary." << endl;
    292                         for (int i=0;i<NDIM;i++) {
    293                                 cout << Verbose(0) << "Enter axis " << i << " boundary: ";
    294                                 cin >> y.x[i];
    295                         }
    296                         mol->CenterEdge((ofstream *)&cout, &x); // make every coordinate positive
    297                         mol->Translate(&y); // translate by boundary
    298                         helper.CopyVector(&y);
    299                         helper.Scale(2.);
    300                         helper.AddVector(&x);
    301                         mol->SetBoxDimension(&helper);  // update Box of atoms by boundary
    302                         break;
    303                 case 'd':
    304                         cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl;
    305                         for (int i=0;i<NDIM;i++) {
    306                                 cout << Verbose(0) << "Enter axis " << i << " boundary: ";
    307                                 cin >> x.x[i];
    308                         }
    309                         // center
    310                         mol->CenterInBox((ofstream *)&cout, &x);
    311                         // update Box of atoms by boundary
    312                         mol->SetBoxDimension(&x);
    313                         break;
    314         }
     265  Vector x, y, helper;
     266  char choice;  // menu choice char
     267
     268  cout << Verbose(0) << "===========CENTER ATOMS=========================" << endl;
     269  cout << Verbose(0) << " a - on origin" << endl;
     270  cout << Verbose(0) << " b - on center of gravity" << endl;
     271  cout << Verbose(0) << " c - within box with additional boundary" << endl;
     272  cout << Verbose(0) << " d - within given simulation box" << endl;
     273  cout << Verbose(0) << "all else - go back" << endl;
     274  cout << Verbose(0) << "===============================================" << endl;
     275  cout << Verbose(0) << "INPUT: ";
     276  cin >> choice;
     277
     278  switch (choice) {
     279    default:
     280      cout << Verbose(0) << "Not a valid choice." << endl;
     281      break;
     282    case 'a':
     283      cout << Verbose(0) << "Centering atoms in config file on origin." << endl;
     284      mol->CenterOrigin((ofstream *)&cout, &x);
     285      break;
     286    case 'b':
     287      cout << Verbose(0) << "Centering atoms in config file on center of gravity." << endl;
     288      mol->CenterGravity((ofstream *)&cout, &x);
     289      break;
     290    case 'c':
     291      cout << Verbose(0) << "Centering atoms in config file within given additional boundary." << endl;
     292      for (int i=0;i<NDIM;i++) {
     293        cout << Verbose(0) << "Enter axis " << i << " boundary: ";
     294        cin >> y.x[i];
     295      }
     296      mol->CenterEdge((ofstream *)&cout, &x);  // make every coordinate positive
     297      mol->Translate(&y); // translate by boundary
     298      helper.CopyVector(&y);
     299      helper.Scale(2.);
     300      helper.AddVector(&x);
     301      mol->SetBoxDimension(&helper);  // update Box of atoms by boundary
     302      break;
     303    case 'd':
     304      cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl;
     305      for (int i=0;i<NDIM;i++) {
     306        cout << Verbose(0) << "Enter axis " << i << " boundary: ";
     307        cin >> x.x[i];
     308      }
     309      // center
     310      mol->CenterInBox((ofstream *)&cout, &x);
     311      // update Box of atoms by boundary
     312      mol->SetBoxDimension(&x);
     313      break;
     314  }
    315315};
    316316
     
    321321static void AlignAtoms(periodentafel *periode, molecule *mol)
    322322{
    323         atom *first, *second, *third;
    324         Vector x,n;
    325         char choice;    // menu choice char
    326 
    327         cout << Verbose(0) << "===========ALIGN ATOMS=========================" << endl;
    328         cout << Verbose(0) << " a - state three atoms defining align plane" << endl;
    329         cout << Verbose(0) << " b - state alignment vector" << endl;
    330         cout << Verbose(0) << " c - state two atoms in alignment direction" << endl;
    331         cout << Verbose(0) << " d - align automatically by least square fit" << endl;
    332         cout << Verbose(0) << "all else - go back" << endl;
    333         cout << Verbose(0) << "===============================================" << endl;
    334         cout << Verbose(0) << "INPUT: ";
    335         cin >> choice;
    336 
    337         switch (choice) {
    338                 default:
    339                 case 'a': // three atoms defining mirror plane
    340                         first = mol->AskAtom("Enter first atom: ");
    341                         second = mol->AskAtom("Enter second atom: ");
    342                         third = mol->AskAtom("Enter third atom: ");
    343 
    344                         n.MakeNormalVector((const Vector *)&first->x,(const Vector *)&second->x,(const Vector *)&third->x);
    345                         break;
    346                 case 'b': // normal vector of mirror plane
    347                         cout << Verbose(0) << "Enter normal vector of mirror plane." << endl;
    348                         n.AskPosition(mol->cell_size,0);
    349                         n.Normalize();
    350                         break;
    351                 case 'c': // three atoms defining mirror plane
    352                         first = mol->AskAtom("Enter first atom: ");
    353                         second = mol->AskAtom("Enter second atom: ");
    354 
    355                         n.CopyVector((const Vector *)&first->x);
    356                         n.SubtractVector((const Vector *)&second->x);
    357                         n.Normalize();
    358                         break;
    359                 case 'd':
    360                         char shorthand[4];
    361                         Vector a;
    362                         struct lsq_params param;
    363                         do {
    364                                 fprintf(stdout, "Enter the element of atoms to be chosen: ");
    365                                 fscanf(stdin, "%3s", shorthand);
    366                         } while ((param.type = periode->FindElement(shorthand)) == NULL);
    367                         cout << Verbose(0) << "Element is " << param.type->name << endl;
    368                         mol->GetAlignvector(&param);
    369                         for (int i=NDIM;i--;) {
    370                                 x.x[i] = gsl_vector_get(param.x,i);
    371                                 n.x[i] = gsl_vector_get(param.x,i+NDIM);
    372                         }
    373                         gsl_vector_free(param.x);
    374                         cout << Verbose(0) << "Offset vector: ";
    375                         x.Output((ofstream *)&cout);
    376                         cout << Verbose(0) << endl;
    377                         n.Normalize();
    378                         break;
    379         };
    380         cout << Verbose(0) << "Alignment vector: ";
    381         n.Output((ofstream *)&cout);
    382         cout << Verbose(0) << endl;
    383         mol->Align(&n);
     323  atom *first, *second, *third;
     324  Vector x,n;
     325  char choice;  // menu choice char
     326
     327  cout << Verbose(0) << "===========ALIGN ATOMS=========================" << endl;
     328  cout << Verbose(0) << " a - state three atoms defining align plane" << endl;
     329  cout << Verbose(0) << " b - state alignment vector" << endl;
     330  cout << Verbose(0) << " c - state two atoms in alignment direction" << endl;
     331  cout << Verbose(0) << " d - align automatically by least square fit" << endl;
     332  cout << Verbose(0) << "all else - go back" << endl;
     333  cout << Verbose(0) << "===============================================" << endl;
     334  cout << Verbose(0) << "INPUT: ";
     335  cin >> choice;
     336
     337  switch (choice) {
     338    default:
     339    case 'a': // three atoms defining mirror plane
     340      first = mol->AskAtom("Enter first atom: ");
     341      second = mol->AskAtom("Enter second atom: ");
     342      third = mol->AskAtom("Enter third atom: ");
     343
     344      n.MakeNormalVector((const Vector *)&first->x,(const Vector *)&second->x,(const Vector *)&third->x);
     345      break;
     346    case 'b': // normal vector of mirror plane
     347      cout << Verbose(0) << "Enter normal vector of mirror plane." << endl;
     348      n.AskPosition(mol->cell_size,0);
     349      n.Normalize();
     350      break;
     351    case 'c': // three atoms defining mirror plane
     352      first = mol->AskAtom("Enter first atom: ");
     353      second = mol->AskAtom("Enter second atom: ");
     354
     355      n.CopyVector((const Vector *)&first->x);
     356      n.SubtractVector((const Vector *)&second->x);
     357      n.Normalize();
     358      break;
     359    case 'd':
     360      char shorthand[4];
     361      Vector a;
     362      struct lsq_params param;
     363      do {
     364        fprintf(stdout, "Enter the element of atoms to be chosen: ");
     365        fscanf(stdin, "%3s", shorthand);
     366      } while ((param.type = periode->FindElement(shorthand)) == NULL);
     367      cout << Verbose(0) << "Element is " << param.type->name << endl;
     368      mol->GetAlignvector(&param);
     369      for (int i=NDIM;i--;) {
     370        x.x[i] = gsl_vector_get(param.x,i);
     371        n.x[i] = gsl_vector_get(param.x,i+NDIM);
     372      }
     373      gsl_vector_free(param.x);
     374      cout << Verbose(0) << "Offset vector: ";
     375      x.Output((ofstream *)&cout);
     376      cout << Verbose(0) << endl;
     377      n.Normalize();
     378      break;
     379  };
     380  cout << Verbose(0) << "Alignment vector: ";
     381  n.Output((ofstream *)&cout);
     382  cout << Verbose(0) << endl;
     383  mol->Align(&n);
    384384};
    385385
     
    389389static void MirrorAtoms(molecule *mol)
    390390{
    391         atom *first, *second, *third;
    392         Vector n;
    393         char choice;    // menu choice char
    394 
    395         cout << Verbose(0) << "===========MIRROR ATOMS=========================" << endl;
    396         cout << Verbose(0) << " a - state three atoms defining mirror plane" << endl;
    397         cout << Verbose(0) << " b - state normal vector of mirror plane" << endl;
    398         cout << Verbose(0) << " c - state two atoms in normal direction" << endl;
    399         cout << Verbose(0) << "all else - go back" << endl;
    400         cout << Verbose(0) << "===============================================" << endl;
    401         cout << Verbose(0) << "INPUT: ";
    402         cin >> choice;
    403 
    404         switch (choice) {
    405                 default:
    406                 case 'a': // three atoms defining mirror plane
    407                         first = mol->AskAtom("Enter first atom: ");
    408                         second = mol->AskAtom("Enter second atom: ");
    409                         third = mol->AskAtom("Enter third atom: ");
    410 
    411                         n.MakeNormalVector((const Vector *)&first->x,(const Vector *)&second->x,(const Vector *)&third->x);
    412                         break;
    413                 case 'b': // normal vector of mirror plane
    414                         cout << Verbose(0) << "Enter normal vector of mirror plane." << endl;
    415                         n.AskPosition(mol->cell_size,0);
    416                         n.Normalize();
    417                         break;
    418                 case 'c': // three atoms defining mirror plane
    419                         first = mol->AskAtom("Enter first atom: ");
    420                         second = mol->AskAtom("Enter second atom: ");
    421 
    422                         n.CopyVector((const Vector *)&first->x);
    423                         n.SubtractVector((const Vector *)&second->x);
    424                         n.Normalize();
    425                         break;
    426         };
    427         cout << Verbose(0) << "Normal vector: ";
    428         n.Output((ofstream *)&cout);
    429         cout << Verbose(0) << endl;
    430         mol->Mirror((const Vector *)&n);
     391  atom *first, *second, *third;
     392  Vector n;
     393  char choice;  // menu choice char
     394
     395  cout << Verbose(0) << "===========MIRROR ATOMS=========================" << endl;
     396  cout << Verbose(0) << " a - state three atoms defining mirror plane" << endl;
     397  cout << Verbose(0) << " b - state normal vector of mirror plane" << endl;
     398  cout << Verbose(0) << " c - state two atoms in normal direction" << endl;
     399  cout << Verbose(0) << "all else - go back" << endl;
     400  cout << Verbose(0) << "===============================================" << endl;
     401  cout << Verbose(0) << "INPUT: ";
     402  cin >> choice;
     403
     404  switch (choice) {
     405    default:
     406    case 'a': // three atoms defining mirror plane
     407      first = mol->AskAtom("Enter first atom: ");
     408      second = mol->AskAtom("Enter second atom: ");
     409      third = mol->AskAtom("Enter third atom: ");
     410
     411      n.MakeNormalVector((const Vector *)&first->x,(const Vector *)&second->x,(const Vector *)&third->x);
     412      break;
     413    case 'b': // normal vector of mirror plane
     414      cout << Verbose(0) << "Enter normal vector of mirror plane." << endl;
     415      n.AskPosition(mol->cell_size,0);
     416      n.Normalize();
     417      break;
     418    case 'c': // three atoms defining mirror plane
     419      first = mol->AskAtom("Enter first atom: ");
     420      second = mol->AskAtom("Enter second atom: ");
     421
     422      n.CopyVector((const Vector *)&first->x);
     423      n.SubtractVector((const Vector *)&second->x);
     424      n.Normalize();
     425      break;
     426  };
     427  cout << Verbose(0) << "Normal vector: ";
     428  n.Output((ofstream *)&cout);
     429  cout << Verbose(0) << endl;
     430  mol->Mirror((const Vector *)&n);
    431431};
    432432
     
    436436static void RemoveAtoms(molecule *mol)
    437437{
    438         atom *first, *second, *third;
    439         int axis;
    440         double tmp1, tmp2;
    441         char choice;    // menu choice char
    442 
    443         cout << Verbose(0) << "===========REMOVE ATOMS=========================" << endl;
    444         cout << Verbose(0) << " a - state atom for removal by number" << endl;
    445         cout << Verbose(0) << " b - keep only in radius around atom" << endl;
    446         cout << Verbose(0) << " c - remove this with one axis greater value" << endl;
    447         cout << Verbose(0) << "all else - go back" << endl;
    448         cout << Verbose(0) << "===============================================" << endl;
    449         cout << Verbose(0) << "INPUT: ";
    450         cin >> choice;
    451 
    452         switch (choice) {
    453                 default:
    454                 case 'a':
    455                         if (mol->RemoveAtom(mol->AskAtom("Enter number of atom within molecule: ")))
    456                                 cout << Verbose(1) << "Atom removed." << endl;
    457                         else
    458                                 cout << Verbose(1) << "Atom not found." << endl;
    459                         break;
    460                 case 'b':
    461                   third = mol->AskAtom("Enter number of atom as reference point: ");
    462                         cout << Verbose(0) << "Enter radius: ";
    463                         cin >> tmp1;
    464                         first = mol->start;
    465       second = first->next;
    466                         while(second != mol->end) {
    467                                 first = second;
    468         second = first->next;
    469                                 if (first->x.DistanceSquared((const Vector *)&third->x) > tmp1*tmp1) // distance to first above radius ...
    470                                         mol->RemoveAtom(first);
    471                         }
    472                         break;
    473                 case 'c':
    474                         cout << Verbose(0) << "Which axis is it: ";
    475                         cin >> axis;
    476                         cout << Verbose(0) << "Lower boundary: ";
    477                         cin >> tmp1;
    478                         cout << Verbose(0) << "Upper boundary: ";
    479                         cin >> tmp2;
    480                         first = mol->start;
     438  atom *first, *second, *third;
     439  int axis;
     440  double tmp1, tmp2;
     441  char choice;  // menu choice char
     442
     443  cout << Verbose(0) << "===========REMOVE ATOMS=========================" << endl;
     444  cout << Verbose(0) << " a - state atom for removal by number" << endl;
     445  cout << Verbose(0) << " b - keep only in radius around atom" << endl;
     446  cout << Verbose(0) << " c - remove this with one axis greater value" << endl;
     447  cout << Verbose(0) << "all else - go back" << endl;
     448  cout << Verbose(0) << "===============================================" << endl;
     449  cout << Verbose(0) << "INPUT: ";
     450  cin >> choice;
     451
     452  switch (choice) {
     453    default:
     454    case 'a':
     455      if (mol->RemoveAtom(mol->AskAtom("Enter number of atom within molecule: ")))
     456        cout << Verbose(1) << "Atom removed." << endl;
     457      else
     458        cout << Verbose(1) << "Atom not found." << endl;
     459      break;
     460    case 'b':
     461      third = mol->AskAtom("Enter number of atom as reference point: ");
     462      cout << Verbose(0) << "Enter radius: ";
     463      cin >> tmp1;
     464      first = mol->start;
    481465      second = first->next;
    482466      while(second != mol->end) {
    483467        first = second;
    484468        second = first->next;
    485                                 if ((first->x.x[axis] < tmp1) || (first->x.x[axis] > tmp2)) {// out of boundary ...
    486                                   //cout << "Atom " << *first << " with " << first->x.x[axis] << " on axis " << axis << " is out of bounds [" << tmp1 << "," << tmp2 << "]." << endl;
    487                                         mol->RemoveAtom(first);
    488                                 }
    489                         }
    490                         break;
    491         };
    492         //mol->Output((ofstream *)&cout);
    493         choice = 'r';
     469        if (first->x.DistanceSquared((const Vector *)&third->x) > tmp1*tmp1) // distance to first above radius ...
     470          mol->RemoveAtom(first);
     471      }
     472      break;
     473    case 'c':
     474      cout << Verbose(0) << "Which axis is it: ";
     475      cin >> axis;
     476      cout << Verbose(0) << "Lower boundary: ";
     477      cin >> tmp1;
     478      cout << Verbose(0) << "Upper boundary: ";
     479      cin >> tmp2;
     480      first = mol->start;
     481      second = first->next;
     482      while(second != mol->end) {
     483        first = second;
     484        second = first->next;
     485        if ((first->x.x[axis] < tmp1) || (first->x.x[axis] > tmp2)) {// out of boundary ...
     486          //cout << "Atom " << *first << " with " << first->x.x[axis] << " on axis " << axis << " is out of bounds [" << tmp1 << "," << tmp2 << "]." << endl;
     487          mol->RemoveAtom(first);
     488        }
     489      }
     490      break;
     491  };
     492  //mol->Output((ofstream *)&cout);
     493  choice = 'r';
    494494};
    495495
     
    500500static void MeasureAtoms(periodentafel *periode, molecule *mol, config *configuration)
    501501{
    502         atom *first, *second, *third;
    503         Vector x,y;
    504         double min[256], tmp1, tmp2, tmp3;
    505         int Z;
    506         char choice;    // menu choice char
    507 
    508         cout << Verbose(0) << "===========MEASURE ATOMS=========================" << endl;
    509         cout << Verbose(0) << " a - calculate bond length between one atom and all others" << endl;
    510         cout << Verbose(0) << " b - calculate bond length between two atoms" << endl;
    511         cout << Verbose(0) << " c - calculate bond angle" << endl;
    512         cout << Verbose(0) << " d - calculate principal axis of the system" << endl;
    513         cout << Verbose(0) << " e - calculate volume of the convex envelope" << endl;
    514         cout << Verbose(0) << " f - calculate temperature from current velocity" << endl;
    515         cout << Verbose(0) << " g - output all temperatures per step from velocities" << endl;
    516         cout << Verbose(0) << "all else - go back" << endl;
    517         cout << Verbose(0) << "===============================================" << endl;
    518         cout << Verbose(0) << "INPUT: ";
    519         cin >> choice;
    520 
    521         switch(choice) {
    522                 default:
    523                         cout << Verbose(1) << "Not a valid choice." << endl;
    524                         break;
    525                 case 'a':
    526                         first = mol->AskAtom("Enter first atom: ");
    527                         for (int i=MAX_ELEMENTS;i--;)
    528                                 min[i] = 0.;
    529 
    530                         second = mol->start;
    531                         while ((second->next != mol->end)) {
    532                                 second = second->next; // advance
    533                                 Z = second->type->Z;
    534                                 tmp1 = 0.;
    535                                 if (first != second) {
    536                                         x.CopyVector((const Vector *)&first->x);
    537                                         x.SubtractVector((const Vector *)&second->x);
    538                                         tmp1 = x.Norm();
    539                                 }
    540                                 if ((tmp1 != 0.) && ((min[Z] == 0.) || (tmp1 < min[Z]))) min[Z] = tmp1;
    541                                 //cout << Verbose(0) << "Bond length between Atom " << first->nr << " and " << second->nr << ": " << tmp1 << " a.u." << endl;
    542                         }
    543                         for (int i=MAX_ELEMENTS;i--;)
    544                                 if (min[i] != 0.) cout << Verbose(0) << "Minimum Bond length between " << first->type->name << " Atom " << first->nr << " and next Ion of type " << (periode->FindElement(i))->name << ": " << min[i] << " a.u." << endl;
    545                         break;
    546 
    547                 case 'b':
    548                         first = mol->AskAtom("Enter first atom: ");
    549                         second = mol->AskAtom("Enter second atom: ");
    550                         for (int i=NDIM;i--;)
    551                                 min[i] = 0.;
    552                         x.CopyVector((const Vector *)&first->x);
    553                         x.SubtractVector((const Vector *)&second->x);
    554                         tmp1 = x.Norm();
    555                         cout << Verbose(1) << "Distance vector is ";
    556                         x.Output((ofstream *)&cout);
    557                         cout << "." << endl << "Norm of distance is " << tmp1 << "." << endl;
    558                         break;
    559 
    560                 case 'c':
    561                         cout << Verbose(0) << "Evaluating bond angle between three - first, central, last - atoms." << endl;
    562                         first = mol->AskAtom("Enter first atom: ");
    563                         second = mol->AskAtom("Enter central atom: ");
    564                         third   = mol->AskAtom("Enter last atom: ");
    565                         tmp1 = tmp2 = tmp3 = 0.;
    566                         x.CopyVector((const Vector *)&first->x);
    567                         x.SubtractVector((const Vector *)&second->x);
    568                         y.CopyVector((const Vector *)&third->x);
    569                         y.SubtractVector((const Vector *)&second->x);
    570                         cout << Verbose(0) << "Bond angle between first atom Nr." << first->nr << ", central atom Nr." << second->nr << " and last atom Nr." << third->nr << ": ";
    571                         cout << Verbose(0) << (acos(x.ScalarProduct((const Vector *)&y)/(y.Norm()*x.Norm()))/M_PI*180.) << " degrees" << endl;
    572                         break;
    573                 case 'd':
    574                         cout << Verbose(0) << "Evaluating prinicipal axis." << endl;
    575                         cout << Verbose(0) << "Shall we rotate? [0/1]: ";
    576                         cin >> Z;
    577                         if ((Z >=0) && (Z <=1))
    578                                 mol->PrincipalAxisSystem((ofstream *)&cout, (bool)Z);
    579                         else
    580                                 mol->PrincipalAxisSystem((ofstream *)&cout, false);
    581                         break;
    582                 case 'e':
    583                         cout << Verbose(0) << "Evaluating volume of the convex envelope.";
    584                         VolumeOfConvexEnvelope((ofstream *)&cout, NULL, configuration, NULL, mol);
    585                         break;
    586                 case 'f':
    587                         mol->OutputTemperatureFromTrajectories((ofstream *)&cout, mol->MDSteps-1, mol->MDSteps, (ofstream *)&cout);
    588                         break;
    589                 case 'g':
    590                         {
    591                                 char filename[255];
    592                                 cout << "Please enter filename: " << endl;
    593                                 cin >> filename;
    594                                 cout << Verbose(1) << "Storing temperatures in " << filename << "." << endl;
    595                                 ofstream *output = new ofstream(filename, ios::trunc);
    596                                 if (!mol->OutputTemperatureFromTrajectories((ofstream *)&cout, 0, mol->MDSteps, output))
    597                                         cout << Verbose(2) << "File could not be written." << endl;
    598                                 else
    599                                         cout << Verbose(2) << "File stored." << endl;
    600                                 output->close();
    601                                 delete(output);
    602                         }
    603                         break;
    604         }
     502  atom *first, *second, *third;
     503  Vector x,y;
     504  double min[256], tmp1, tmp2, tmp3;
     505  int Z;
     506  char choice;  // menu choice char
     507
     508  cout << Verbose(0) << "===========MEASURE ATOMS=========================" << endl;
     509  cout << Verbose(0) << " a - calculate bond length between one atom and all others" << endl;
     510  cout << Verbose(0) << " b - calculate bond length between two atoms" << endl;
     511  cout << Verbose(0) << " c - calculate bond angle" << endl;
     512  cout << Verbose(0) << " d - calculate principal axis of the system" << endl;
     513  cout << Verbose(0) << " e - calculate volume of the convex envelope" << endl;
     514  cout << Verbose(0) << " f - calculate temperature from current velocity" << endl;
     515  cout << Verbose(0) << " g - output all temperatures per step from velocities" << endl;
     516  cout << Verbose(0) << "all else - go back" << endl;
     517  cout << Verbose(0) << "===============================================" << endl;
     518  cout << Verbose(0) << "INPUT: ";
     519  cin >> choice;
     520
     521  switch(choice) {
     522    default:
     523      cout << Verbose(1) << "Not a valid choice." << endl;
     524      break;
     525    case 'a':
     526      first = mol->AskAtom("Enter first atom: ");
     527      for (int i=MAX_ELEMENTS;i--;)
     528        min[i] = 0.;
     529
     530      second = mol->start;
     531      while ((second->next != mol->end)) {
     532        second = second->next; // advance
     533        Z = second->type->Z;
     534        tmp1 = 0.;
     535        if (first != second) {
     536          x.CopyVector((const Vector *)&first->x);
     537          x.SubtractVector((const Vector *)&second->x);
     538          tmp1 = x.Norm();
     539        }
     540        if ((tmp1 != 0.) && ((min[Z] == 0.) || (tmp1 < min[Z]))) min[Z] = tmp1;
     541        //cout << Verbose(0) << "Bond length between Atom " << first->nr << " and " << second->nr << ": " << tmp1 << " a.u." << endl;
     542      }
     543      for (int i=MAX_ELEMENTS;i--;)
     544        if (min[i] != 0.) cout << Verbose(0) << "Minimum Bond length between " << first->type->name << " Atom " << first->nr << " and next Ion of type " << (periode->FindElement(i))->name << ": " << min[i] << " a.u." << endl;
     545      break;
     546
     547    case 'b':
     548      first = mol->AskAtom("Enter first atom: ");
     549      second = mol->AskAtom("Enter second atom: ");
     550      for (int i=NDIM;i--;)
     551        min[i] = 0.;
     552      x.CopyVector((const Vector *)&first->x);
     553      x.SubtractVector((const Vector *)&second->x);
     554      tmp1 = x.Norm();
     555      cout << Verbose(1) << "Distance vector is ";
     556      x.Output((ofstream *)&cout);
     557      cout << "." << endl << "Norm of distance is " << tmp1 << "." << endl;
     558      break;
     559
     560    case 'c':
     561      cout << Verbose(0) << "Evaluating bond angle between three - first, central, last - atoms." << endl;
     562      first = mol->AskAtom("Enter first atom: ");
     563      second = mol->AskAtom("Enter central atom: ");
     564      third  = mol->AskAtom("Enter last atom: ");
     565      tmp1 = tmp2 = tmp3 = 0.;
     566      x.CopyVector((const Vector *)&first->x);
     567      x.SubtractVector((const Vector *)&second->x);
     568      y.CopyVector((const Vector *)&third->x);
     569      y.SubtractVector((const Vector *)&second->x);
     570      cout << Verbose(0) << "Bond angle between first atom Nr." << first->nr << ", central atom Nr." << second->nr << " and last atom Nr." << third->nr << ": ";
     571      cout << Verbose(0) << (acos(x.ScalarProduct((const Vector *)&y)/(y.Norm()*x.Norm()))/M_PI*180.) << " degrees" << endl;
     572      break;
     573    case 'd':
     574      cout << Verbose(0) << "Evaluating prinicipal axis." << endl;
     575      cout << Verbose(0) << "Shall we rotate? [0/1]: ";
     576      cin >> Z;
     577      if ((Z >=0) && (Z <=1))
     578        mol->PrincipalAxisSystem((ofstream *)&cout, (bool)Z);
     579      else
     580        mol->PrincipalAxisSystem((ofstream *)&cout, false);
     581      break;
     582    case 'e':
     583      cout << Verbose(0) << "Evaluating volume of the convex envelope.";
     584      VolumeOfConvexEnvelope((ofstream *)&cout, NULL, configuration, NULL, mol);
     585      break;
     586    case 'f':
     587      mol->OutputTemperatureFromTrajectories((ofstream *)&cout, mol->MDSteps-1, mol->MDSteps, (ofstream *)&cout);
     588      break;
     589    case 'g':
     590      {
     591        char filename[255];
     592        cout << "Please enter filename: " << endl;
     593        cin >> filename;
     594        cout << Verbose(1) << "Storing temperatures in " << filename << "." << endl;
     595        ofstream *output = new ofstream(filename, ios::trunc);
     596        if (!mol->OutputTemperatureFromTrajectories((ofstream *)&cout, 0, mol->MDSteps, output))
     597          cout << Verbose(2) << "File could not be written." << endl;
     598        else
     599          cout << Verbose(2) << "File stored." << endl;
     600        output->close();
     601        delete(output);
     602      }
     603      break;
     604  }
    605605};
    606606
     
    611611static void FragmentAtoms(molecule *mol, config *configuration)
    612612{
    613         int Order1;
    614         clock_t start, end;
    615 
    616         cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl;
    617         cout << Verbose(0) << "What's the desired bond order: ";
    618         cin >> Order1;
    619         if (mol->first->next != mol->last) {    // there are bonds
    620                 start = clock();
    621                 mol->FragmentMolecule((ofstream *)&cout, Order1, configuration);
    622                 end = clock();
    623                 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
    624         } else
    625                 cout << Verbose(0) << "Connection matrix has not yet been generated!" << endl;
     613  int Order1;
     614  clock_t start, end;
     615
     616  cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl;
     617  cout << Verbose(0) << "What's the desired bond order: ";
     618  cin >> Order1;
     619  if (mol->first->next != mol->last) {  // there are bonds
     620    start = clock();
     621    mol->FragmentMolecule((ofstream *)&cout, Order1, configuration);
     622    end = clock();
     623    cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
     624  } else
     625    cout << Verbose(0) << "Connection matrix has not yet been generated!" << endl;
    626626};
    627627
     
    10531053static void testroutine(MoleculeListClass *molecules)
    10541054{
    1055         // the current test routine checks the functionality of the KeySet&Graph concept:
    1056         // We want to have a multiindex (the KeySet) describing a unique subgraph
     1055  // the current test routine checks the functionality of the KeySet&Graph concept:
     1056  // We want to have a multiindex (the KeySet) describing a unique subgraph
    10571057  int i, comp, counter=0;
    10581058
     
    10671067  atom *Walker = mol->start;
    10681068
    1069         // generate some KeySets
    1070         cout << "Generating KeySets." << endl;
    1071         KeySet TestSets[mol->AtomCount+1];
    1072         i=1;
    1073         while (Walker->next != mol->end) {
    1074                 Walker = Walker->next;
    1075                 for (int j=0;j<i;j++) {
    1076                         TestSets[j].insert(Walker->nr);
    1077                 }
    1078                 i++;
    1079         }
    1080         cout << "Testing insertion of already present item in KeySets." << endl;
    1081         KeySetTestPair test;
    1082         test = TestSets[mol->AtomCount-1].insert(Walker->nr);
    1083         if (test.second) {
    1084                 cout << Verbose(1) << "Insertion worked?!" << endl;
    1085         } else {
    1086                 cout << Verbose(1) << "Insertion rejected: Present object is " << (*test.first) << "." << endl;
    1087         }
    1088         TestSets[mol->AtomCount].insert(mol->end->previous->nr);
    1089         TestSets[mol->AtomCount].insert(mol->end->previous->previous->previous->nr);
    1090 
    1091         // constructing Graph structure
    1092         cout << "Generating Subgraph class." << endl;
    1093         Graph Subgraphs;
    1094 
    1095         // insert KeySets into Subgraphs
    1096         cout << "Inserting KeySets into Subgraph class." << endl;
    1097         for (int j=0;j<mol->AtomCount;j++) {
    1098                 Subgraphs.insert(GraphPair (TestSets[j],pair<int, double>(counter++, 1.)));
    1099         }
    1100         cout << "Testing insertion of already present item in Subgraph." << endl;
    1101         GraphTestPair test2;
    1102         test2 = Subgraphs.insert(GraphPair (TestSets[mol->AtomCount],pair<int, double>(counter++, 1.)));
    1103         if (test2.second) {
    1104                 cout << Verbose(1) << "Insertion worked?!" << endl;
    1105         } else {
    1106                 cout << Verbose(1) << "Insertion rejected: Present object is " << (*(test2.first)).second.first << "." << endl;
    1107         }
    1108 
    1109         // show graphs
    1110         cout << "Showing Subgraph's contents, checking that it's sorted." << endl;
    1111         Graph::iterator A = Subgraphs.begin();
    1112         while (A !=     Subgraphs.end()) {
    1113                 cout << (*A).second.first << ": ";
    1114                 KeySet::iterator key = (*A).first.begin();
    1115                 comp = -1;
    1116                 while (key != (*A).first.end()) {
    1117                         if ((*key) > comp)
    1118                                 cout << (*key) << " ";
    1119                         else
    1120                                 cout << (*key) << "! ";
    1121                         comp = (*key);
    1122                         key++;
    1123                 }
    1124                 cout << endl;
    1125                 A++;
    1126         }
    1127         delete(mol);
     1069  // generate some KeySets
     1070  cout << "Generating KeySets." << endl;
     1071  KeySet TestSets[mol->AtomCount+1];
     1072  i=1;
     1073  while (Walker->next != mol->end) {
     1074    Walker = Walker->next;
     1075    for (int j=0;j<i;j++) {
     1076      TestSets[j].insert(Walker->nr);
     1077    }
     1078    i++;
     1079  }
     1080  cout << "Testing insertion of already present item in KeySets." << endl;
     1081  KeySetTestPair test;
     1082  test = TestSets[mol->AtomCount-1].insert(Walker->nr);
     1083  if (test.second) {
     1084    cout << Verbose(1) << "Insertion worked?!" << endl;
     1085  } else {
     1086    cout << Verbose(1) << "Insertion rejected: Present object is " << (*test.first) << "." << endl;
     1087  }
     1088  TestSets[mol->AtomCount].insert(mol->end->previous->nr);
     1089  TestSets[mol->AtomCount].insert(mol->end->previous->previous->previous->nr);
     1090
     1091  // constructing Graph structure
     1092  cout << "Generating Subgraph class." << endl;
     1093  Graph Subgraphs;
     1094
     1095  // insert KeySets into Subgraphs
     1096  cout << "Inserting KeySets into Subgraph class." << endl;
     1097  for (int j=0;j<mol->AtomCount;j++) {
     1098    Subgraphs.insert(GraphPair (TestSets[j],pair<int, double>(counter++, 1.)));
     1099  }
     1100  cout << "Testing insertion of already present item in Subgraph." << endl;
     1101  GraphTestPair test2;
     1102  test2 = Subgraphs.insert(GraphPair (TestSets[mol->AtomCount],pair<int, double>(counter++, 1.)));
     1103  if (test2.second) {
     1104    cout << Verbose(1) << "Insertion worked?!" << endl;
     1105  } else {
     1106    cout << Verbose(1) << "Insertion rejected: Present object is " << (*(test2.first)).second.first << "." << endl;
     1107  }
     1108
     1109  // show graphs
     1110  cout << "Showing Subgraph's contents, checking that it's sorted." << endl;
     1111  Graph::iterator A = Subgraphs.begin();
     1112  while (A !=  Subgraphs.end()) {
     1113    cout << (*A).second.first << ": ";
     1114    KeySet::iterator key = (*A).first.begin();
     1115    comp = -1;
     1116    while (key != (*A).first.end()) {
     1117      if ((*key) > comp)
     1118        cout << (*key) << " ";
     1119      else
     1120        cout << (*key) << "! ";
     1121      comp = (*key);
     1122      key++;
     1123    }
     1124    cout << endl;
     1125    A++;
     1126  }
     1127  delete(mol);
    11281128};
    11291129
     
    11361136static void SaveConfig(char *ConfigFileName, config *configuration, periodentafel *periode, MoleculeListClass *molecules)
    11371137{
    1138         char filename[MAXSTRINGSIZE];
    1139         ofstream output;
    1140         molecule *mol = new molecule(periode);
    1141 
    1142         // merge all molecules in MoleculeListClass into this molecule
    1143         int N = molecules->ListOfMolecules.size();
    1144         int *src = new int(N);
    1145         N=0;
    1146         for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
    1147           src[N++] = (*ListRunner)->IndexNr;
    1148         molecules->SimpleMultiAdd(mol, src, N);
    1149 
    1150         cout << Verbose(0) << "Storing configuration ... " << endl;
    1151         // get correct valence orbitals
    1152         mol->CalculateOrbitals(*configuration);
    1153         configuration->InitMaxMinStopStep = configuration->MaxMinStopStep = configuration->MaxPsiDouble;
    1154         strcpy(filename, ConfigFileName);
    1155         if (ConfigFileName != NULL) { // test the file name
    1156                 output.open(ConfigFileName, ios::trunc);
    1157         } else if (strlen(configuration->configname) != 0) {
    1158                 strcpy(filename, configuration->configname);
    1159                 output.open(configuration->configname, ios::trunc);
    1160                 } else {
    1161                         strcpy(filename, DEFAULTCONFIG);
    1162                         output.open(DEFAULTCONFIG, ios::trunc);
    1163                 }
    1164         output.close();
    1165         output.clear();
    1166         cout << Verbose(0) << "Saving of config file ";
    1167         if (configuration->Save(filename, periode, mol))
    1168                 cout << "successful." << endl;
    1169         else
    1170                 cout << "failed." << endl;
    1171 
    1172         // and save to xyz file
    1173         if (ConfigFileName != NULL) {
    1174                 strcpy(filename, ConfigFileName);
    1175                 strcat(filename, ".xyz");
    1176                 output.open(filename, ios::trunc);
    1177         }
    1178         if (output == NULL) {
    1179                 strcpy(filename,"main_pcp_linux");
    1180                 strcat(filename, ".xyz");
    1181                 output.open(filename, ios::trunc);
    1182         }
    1183         cout << Verbose(0) << "Saving of XYZ file ";
    1184         if (mol->MDSteps <= 1) {
    1185                 if (mol->OutputXYZ(&output))
    1186                         cout << "successful." << endl;
    1187                 else
    1188                         cout << "failed." << endl;
    1189         } else {
    1190                 if (mol->OutputTrajectoriesXYZ(&output))
    1191                         cout << "successful." << endl;
    1192                 else
    1193                         cout << "failed." << endl;
    1194         }
    1195         output.close();
    1196         output.clear();
    1197 
    1198         // and save as MPQC configuration
    1199         if (ConfigFileName != NULL)
    1200                 strcpy(filename, ConfigFileName);
    1201         if (output == NULL)
    1202                 strcpy(filename,"main_pcp_linux");
    1203         cout << Verbose(0) << "Saving as mpqc input ";
    1204         if (configuration->SaveMPQC(filename, mol))
    1205                 cout << "done." << endl;
    1206         else
    1207                 cout << "failed." << endl;
    1208 
    1209         if (!strcmp(configuration->configpath, configuration->GetDefaultPath())) {
    1210                 cerr << "WARNING: config is found under different path then stated in config file::defaultpath!" << endl;
    1211         }
    1212         delete(mol);
     1138  char filename[MAXSTRINGSIZE];
     1139  ofstream output;
     1140  molecule *mol = new molecule(periode);
     1141
     1142  // merge all molecules in MoleculeListClass into this molecule
     1143  int N = molecules->ListOfMolecules.size();
     1144  int *src = new int(N);
     1145  N=0;
     1146  for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
     1147    src[N++] = (*ListRunner)->IndexNr;
     1148  molecules->SimpleMultiAdd(mol, src, N);
     1149
     1150  cout << Verbose(0) << "Storing configuration ... " << endl;
     1151  // get correct valence orbitals
     1152  mol->CalculateOrbitals(*configuration);
     1153  configuration->InitMaxMinStopStep = configuration->MaxMinStopStep = configuration->MaxPsiDouble;
     1154  strcpy(filename, ConfigFileName);
     1155  if (ConfigFileName != NULL) { // test the file name
     1156    output.open(ConfigFileName, ios::trunc);
     1157  } else if (strlen(configuration->configname) != 0) {
     1158    strcpy(filename, configuration->configname);
     1159    output.open(configuration->configname, ios::trunc);
     1160    } else {
     1161      strcpy(filename, DEFAULTCONFIG);
     1162      output.open(DEFAULTCONFIG, ios::trunc);
     1163    }
     1164  output.close();
     1165  output.clear();
     1166  cout << Verbose(0) << "Saving of config file ";
     1167  if (configuration->Save(filename, periode, mol))
     1168    cout << "successful." << endl;
     1169  else
     1170    cout << "failed." << endl;
     1171
     1172  // and save to xyz file
     1173  if (ConfigFileName != NULL) {
     1174    strcpy(filename, ConfigFileName);
     1175    strcat(filename, ".xyz");
     1176    output.open(filename, ios::trunc);
     1177  }
     1178  if (output == NULL) {
     1179    strcpy(filename,"main_pcp_linux");
     1180    strcat(filename, ".xyz");
     1181    output.open(filename, ios::trunc);
     1182  }
     1183  cout << Verbose(0) << "Saving of XYZ file ";
     1184  if (mol->MDSteps <= 1) {
     1185    if (mol->OutputXYZ(&output))
     1186      cout << "successful." << endl;
     1187    else
     1188      cout << "failed." << endl;
     1189  } else {
     1190    if (mol->OutputTrajectoriesXYZ(&output))
     1191      cout << "successful." << endl;
     1192    else
     1193      cout << "failed." << endl;
     1194  }
     1195  output.close();
     1196  output.clear();
     1197
     1198  // and save as MPQC configuration
     1199  if (ConfigFileName != NULL)
     1200    strcpy(filename, ConfigFileName);
     1201  if (output == NULL)
     1202    strcpy(filename,"main_pcp_linux");
     1203  cout << Verbose(0) << "Saving as mpqc input ";
     1204  if (configuration->SaveMPQC(filename, mol))
     1205    cout << "done." << endl;
     1206  else
     1207    cout << "failed." << endl;
     1208
     1209  if (!strcmp(configuration->configpath, configuration->GetDefaultPath())) {
     1210    cerr << "WARNING: config is found under different path then stated in config file::defaultpath!" << endl;
     1211  }
     1212  delete(mol);
    12131213};
    12141214
     
    12251225static int ParseCommandLineOptions(int argc, char **argv, MoleculeListClass *&molecules, periodentafel *&periode, config& configuration, char *&ConfigFileName, char *&PathToDatabases)
    12261226{
    1227         Vector x,y,z,n; // coordinates for absolute point in cell volume
    1228         double *factor; // unit factor if desired
    1229         ifstream test;
    1230         ofstream output;
    1231         string line;
    1232         atom *first;
    1233         bool SaveFlag = false;
    1234         int ExitFlag = 0;
    1235         int j;
    1236         double volume = 0.;
    1237         enum ConfigStatus config_present = absent;
    1238         clock_t start,end;
    1239         int argptr;
    1240         PathToDatabases = LocalPath;
    1241 
    1242         // simply create a new molecule, wherein the config file is loaded and the manipulation takes place
    1243         molecule *mol = new molecule(periode);
    1244         molecules->insert(mol);
    1245 
    1246         if (argc > 1) { // config file specified as option
    1247                 // 1. : Parse options that just set variables or print help
    1248                 argptr = 1;
    1249                 do {
    1250                         if (argv[argptr][0] == '-') {
    1251                                 cout << Verbose(0) << "Recognized command line argument: " << argv[argptr][1] << ".\n";
    1252                                 argptr++;
    1253                                 switch(argv[argptr-1][1]) {
    1254                                         case 'h':
    1255                                         case 'H':
    1256                                         case '?':
    1257                                                 cout << "MoleCuilder suite" << endl << "==================" << endl << endl;
    1258                                                 cout << "Usage: " << argv[0] << "[config file] [-{acefpsthH?vfrp}] [further arguments]" << endl;
    1259                                                 cout << "or simply " << argv[0] << " without arguments for interactive session." << endl;
    1260                                                 cout << "\t-a Z x1 x2 x3\tAdd new atom of element Z at coordinates (x1,x2,x3)." << endl;
    1261                                                 cout << "\t-A <source>\tCreate adjacency list from bonds parsed from 'dbond'-style file." <<endl;
    1262                                                 cout << "\t-b x1 x2 x3\tCenter atoms in domain with given edge lengths of (x1,x2,x3)." << endl;
    1263                                                 cout << "\t-B <basis>\tSetting basis to store to MPQC config files." << endl;
    1264                                                 cout << "\t-c x1 x2 x3\tCenter atoms in domain with a minimum distance to boundary of (x1,x2,x3)." << endl;
    1265                                                 cout << "\t-D <bond distance>\tDepth-First-Search Analysis of the molecule, giving cycles and tree/back edges." << endl;
    1266                                                 cout << "\t-O\tCenter atoms in origin." << endl;
    1267                                                 cout << "\t-d x1 x2 x3\tDuplicate cell along each axis by given factor." << endl;
    1268                                                 cout << "\t-e <file>\tSets the databases path to be parsed (default: ./)." << endl;
    1269                                                 cout << "\t-E <id> <Z>\tChange atom <id>'s element to <Z>, <id> begins at 0." << endl;
    1270                                                 cout << "\t-f/F <dist> <order>\tFragments the molecule in BOSSANOVA manner (with/out rings compressed) and stores config files in same dir as config (return code 0 - fragmented, 2 - no fragmentation necessary)." << endl;
    1271                                                 cout << "\t-h/-H/-?\tGive this help screen." << endl;
    1272                                                 cout << "\t-m <0/1>\tCalculate (0)/ Align in(1) PAS with greatest EV along z axis." << endl;
    1273                                                 cout << "\t-n\tFast parsing (i.e. no trajectories are looked for)." << endl;
    1274                                                 cout << "\t-N <radius> <file>\tGet non-convex-envelope." << endl;
    1275                                                 cout << "\t-o <out>\tGet volume of the convex envelope (and store to tecplot file)." << endl;
    1276                                                 cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl;
    1277                                                 cout << "\t-P <file>\tParse given forces file and append as an MD step to config file via Verlet." << endl;
    1278                                                 cout << "\t-r\t\tConvert file from an old pcp syntax." << endl;
    1279                                                 cout << "\t-R\t\tRemove all atoms out of sphere around a given one." << endl;
    1280                                                 cout << "\t-t x1 x2 x3\tTranslate all atoms by this vector (x1,x2,x3)." << endl;
    1281                                                 cout << "\t-T <file> Store temperatures from the config file in <file>." << endl;
    1282                                                 cout << "\t-s x1 x2 x3\tScale all atom coordinates by this vector (x1,x2,x3)." << endl;
    1283                                                 cout << "\t-u rho\tsuspend in water solution and output necessary cell lengths, average density rho and repetition." << endl;
    1284                                                 cout << "\t-v/-V\t\tGives version information." << endl;
    1285                                                 cout << "Note: config files must not begin with '-' !" << endl;
    1286                                                 delete(mol);
    1287                                                 delete(periode);
    1288                                                 return (1);
    1289                                                 break;
    1290                                         case 'v':
    1291                                         case 'V':
    1292                                                 cout << argv[0] << " " << VERSIONSTRING << endl;
    1293                                                 cout << "Build your own molecule position set." << endl;
    1294                                                 delete(mol);
    1295                                                 delete(periode);
    1296                                                 return (1);
    1297                                                 break;
    1298                                         case 'e':
    1299                                                 if ((argptr >= argc) || (argv[argptr][0] == '-')) {
    1300                                                         cerr << "Not enough or invalid arguments for specifying element db: -e <db file>" << endl;
    1301                                                 } else {
    1302                                                         cout << "Using " << argv[argptr] << " as elements database." << endl;
    1303                                                         PathToDatabases = argv[argptr];
    1304                                                         argptr+=1;
    1305                                                 }
    1306                                                 break;
    1307                                         case 'n':
    1308                                                 cout << "I won't parse trajectories." << endl;
    1309                                                 configuration.FastParsing = true;
    1310                                                 break;
    1311                                         default:        // no match? Step on
    1312                                                 argptr++;
    1313                                                 break;
    1314                                 }
    1315                         } else
    1316                                 argptr++;
    1317                 } while (argptr < argc);
    1318 
    1319                 // 2. Parse the element database
    1320                 if (periode->LoadPeriodentafel(PathToDatabases)) {
    1321                         cout << Verbose(0) << "Element list loaded successfully." << endl;
    1322                         //periode->Output((ofstream *)&cout);
    1323                 } else {
    1324                         cout << Verbose(0) << "Element list loading failed." << endl;
    1325                         return 1;
    1326                 }
    1327                 // 3. Find config file name and parse if possible
    1328                 if (argv[1][0] != '-') {
    1329                         cout << Verbose(0) << "Config file given." << endl;
    1330                         test.open(argv[1], ios::in);
    1331                         if (test == NULL) {
    1332                                 //return (1);
    1333                                 output.open(argv[1], ios::out);
    1334                                 if (output == NULL) {
    1335                                         cout << Verbose(1) << "Specified config file " << argv[1] << " not found." << endl;
    1336                                         config_present = absent;
    1337                                 } else {
    1338                                         cout << "Empty configuration file." << endl;
    1339                                         ConfigFileName = argv[1];
    1340                                         config_present = empty;
    1341                                         output.close();
    1342                                 }
    1343                         } else {
    1344                                 test.close();
    1345                                 ConfigFileName = argv[1];
    1346                                 cout << Verbose(1) << "Specified config file found, parsing ... ";
    1347                                 switch (configuration.TestSyntax(ConfigFileName, periode, mol)) {
    1348                                         case 1:
    1349                                                 cout << "new syntax." << endl;
    1350                                                 configuration.Load(ConfigFileName, periode, mol);
    1351                                                 config_present = present;
    1352                                                 break;
    1353                                         case 0:
    1354                                                 cout << "old syntax." << endl;
    1355                                                 configuration.LoadOld(ConfigFileName, periode, mol);
    1356                                                 config_present = present;
    1357                                                 break;
    1358                                         default:
    1359                                                 cout << "Unknown syntax or empty, yet present file." << endl;
    1360                                                 config_present = empty;
    1361                         }
    1362                         }
    1363                 } else
    1364                         config_present = absent;
    1365                 // 4. parse again through options, now for those depending on elements db and config presence
    1366                 argptr = 1;
    1367                 do {
    1368                         cout << "Current Command line argument: " << argv[argptr] << "." << endl;
    1369                         if (argv[argptr][0] == '-') {
    1370                                 argptr++;
    1371                                 if ((config_present == present) || (config_present == empty)) {
    1372                                         switch(argv[argptr-1][1]) {
    1373                                                 case 'p':
    1374                                                         ExitFlag = 1;
    1375                                                         if ((argptr >= argc) || (argv[argptr][0] == '-')) {
    1376                                                                 ExitFlag = 255;
    1377                                                                 cerr << "Not enough arguments for parsing: -p <xyz file>" << endl;
    1378                                                         } else {
    1379                                                                 SaveFlag = true;
    1380                                                                 cout << Verbose(1) << "Parsing xyz file for new atoms." << endl;
    1381                                                                 if (!mol->AddXYZFile(argv[argptr]))
    1382                                                                         cout << Verbose(2) << "File not found." << endl;
    1383                                                                 else {
    1384                                                                         cout << Verbose(2) << "File found and parsed." << endl;
    1385                                                                         config_present = present;
    1386                                                                 }
    1387                                                         }
    1388                                                         break;
    1389                                                 case 'a':
    1390                                                         ExitFlag = 1;
    1391                                                         if ((argptr >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr+1]))) {
    1392                                                                 ExitFlag = 255;
    1393                                                                 cerr << "Not enough or invalid arguments for adding atom: -a <element> <x> <y> <z>" << endl;
    1394                                                         } else {
    1395                                                                 SaveFlag = true;
    1396                                                                 cout << Verbose(1) << "Adding new atom with element " << argv[argptr] << " at (" << argv[argptr+1] << "," << argv[argptr+2] << "," << argv[argptr+3] << "), ";
    1397                                                                 first = new atom;
    1398                                                                 first->type = periode->FindElement(atoi(argv[argptr]));
    1399                                                                 if (first->type != NULL)
    1400                                                                         cout << Verbose(2) << "found element " << first->type->name << endl;
    1401                                                                 for (int i=NDIM;i--;)
    1402                                                                         first->x.x[i] = atof(argv[argptr+1+i]);
    1403                                                                 if (first->type != NULL) {
    1404                                                                         mol->AddAtom(first);    // add to molecule
    1405                                                                         if ((config_present == empty) && (mol->AtomCount != 0))
    1406                                                                                 config_present = present;
    1407                                                                 } else
    1408                                                                         cerr << Verbose(1) << "Could not find the specified element." << endl;
    1409                                                                 argptr+=4;
    1410                                                         }
    1411                                                         break;
    1412                                                 default:        // no match? Don't step on (this is done in next switch's default)
    1413                                                         break;
    1414                                         }
    1415                                 }
    1416                                 if (config_present == present) {
    1417                                         switch(argv[argptr-1][1]) {
    1418                                                 case 'B':
    1419                                                         if ((argptr >= argc) || (argv[argptr][0] == '-')) {
    1420                                                                 ExitFlag = 255;
    1421                                                                 cerr << "Not enough or invalid arguments given for setting MPQC basis: -B <basis name>" << endl;
    1422                                                         } else {
    1423                                                                 configuration.basis = argv[argptr];
    1424                                                                 cout << Verbose(1) << "Setting MPQC basis to " << configuration.basis << "." << endl;
    1425                                                                 argptr+=1;
    1426                                                         }
    1427                                                         break;
    1428                                                 case 'D':
    1429                                                         ExitFlag = 1;
    1430                                                         {
    1431                                                                 cout << Verbose(1) << "Depth-First-Search Analysis." << endl;
    1432                                                                 MoleculeLeafClass *Subgraphs = NULL;                    // list of subgraphs from DFS analysis
    1433                                                                 int *MinimumRingSize = new int[mol->AtomCount];
    1434                                                                 atom ***ListOfLocalAtoms = NULL;
    1435                                                                 int FragmentCounter = 0;
    1436                                                                 class StackClass<bond *> *BackEdgeStack = NULL;
    1437                                                                 class StackClass<bond *> *LocalBackEdgeStack = NULL;
    1438                                                                 mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr]), configuration.GetIsAngstroem());
    1439                                                                 mol->CreateListOfBondsPerAtom((ofstream *)&cout);
    1440                                                                 Subgraphs = mol->DepthFirstSearchAnalysis((ofstream *)&cout, BackEdgeStack);
    1441                                                                 if (Subgraphs != NULL) {
    1442                                                                         Subgraphs->next->FillBondStructureFromReference((ofstream *)&cout, mol, (FragmentCounter = 0), ListOfLocalAtoms, false);        // we want to keep the created ListOfLocalAtoms
    1443                                                                         while (Subgraphs->next != NULL) {
    1444                                                                                 Subgraphs = Subgraphs->next;
    1445                                                                                 LocalBackEdgeStack = new StackClass<bond *> (Subgraphs->Leaf->BondCount);
    1446                                                                                 Subgraphs->Leaf->PickLocalBackEdges((ofstream *)&cout, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack);
    1447                                                                                 Subgraphs->Leaf->CyclicStructureAnalysis((ofstream *)&cout, BackEdgeStack, MinimumRingSize);
    1448                                                                                 delete(LocalBackEdgeStack);
    1449                                                                                 delete(Subgraphs->previous);
    1450                                                                         }
    1451                                                                         delete(Subgraphs);
    1452                                                                         for (int i=0;i<FragmentCounter;i++)
    1453                                                                                 Free((void **)&ListOfLocalAtoms[FragmentCounter], "ParseCommandLineOptions: **ListOfLocalAtoms[]");
    1454                                                                         Free((void **)&ListOfLocalAtoms, "ParseCommandLineOptions: ***ListOfLocalAtoms");
    1455                                                                 }
    1456                                                                 delete(BackEdgeStack);
    1457                                                                 delete[](MinimumRingSize);
    1458                                                         }
    1459                                                         //argptr+=1;
    1460                                                         break;
    1461                                                 case 'E':
    1462                                                         ExitFlag = 1;
    1463                                                         if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (argv[argptr+1][0] == '-')) {
    1464                                                                 ExitFlag = 255;
    1465                                                                 cerr << "Not enough or invalid arguments given for changing element: -E <atom nr.> <element>" << endl;
    1466                                                         } else {
    1467                                                                 SaveFlag = true;
    1468                                                                 cout << Verbose(1) << "Changing atom " << argv[argptr] << " to element " << argv[argptr+1] << "." << endl;
    1469                                                                 first = mol->FindAtom(atoi(argv[argptr]));
    1470                                                                 first->type = periode->FindElement(atoi(argv[argptr+1]));
    1471                                                                 argptr+=2;
    1472                                                         }
    1473                                                         break;
    1474                                                 case 'A':
    1475                                                         ExitFlag = 1;
    1476                                                         if ((argptr >= argc) || (argv[argptr][0] == '-')) {
    1477                                                                 ExitFlag =255;
    1478                                                                 cerr << "Missing source file for bonds in molecule: -A <bond sourcefile>" << endl;
    1479                                                         } else {
    1480                                                                 cout << "Parsing bonds from " << argv[argptr] << "." << endl;
    1481                                                                 ifstream *input = new ifstream(argv[argptr]);
    1482                                                                 mol->CreateAdjacencyList2((ofstream *)&cout, input);
    1483                                                                 input->close();
    1484                                                                 argptr+=1;
    1485                                                         }
    1486                                                         break;
    1487                                                 case 'N':
    1488                                                         ExitFlag = 1;
    1489                                                         if ((argptr+1 >= argc) || (argv[argptr+1][0] == '-')){
    1490                                                                 ExitFlag = 255;
    1491                                                                 cerr << "Not enough or invalid arguments given for non-convex envelope: -o <radius> <tecplot output file>" << endl;
    1492                                                         } else {
    1493                                                                 class Tesselation T;
    1494                                                                 int N = 15;
    1495                                                                 int number = 100;
    1496                                                                 string filename(argv[argptr+1]);
    1497                                                                 filename.append(".csv");
    1498                                                                 cout << Verbose(0) << "Evaluating non-convex envelope.";
    1499                                                                 cout << Verbose(1) << "Using rolling ball of radius " << atof(argv[argptr]) << " and storing tecplot data in " << argv[argptr+1] << "." << endl;
    1500                                                                 LinkedCell LCList(mol, atof(argv[argptr]));             // \NOTE not twice the radius??
    1501                                                                 Find_non_convex_border((ofstream *)&cout, mol, &T, &LCList, argv[argptr+1], atof(argv[argptr]));
    1502                                                                 //FindDistributionOfEllipsoids((ofstream *)&cout, &T, &LCList, N, number, filename.c_str());
    1503                                                                 argptr+=2;
    1504                                                         }
    1505                                                         break;
    1506                                                 case 'T':
    1507                                                         ExitFlag = 1;
    1508                                                         if ((argptr >= argc) || (argv[argptr][0] == '-')) {
    1509                                                                 ExitFlag = 255;
    1510                                                                 cerr << "Not enough or invalid arguments given for storing tempature: -T <temperature file>" << endl;
    1511                                                         } else {
    1512                                                                 cout << Verbose(1) << "Storing temperatures in " << argv[argptr] << "." << endl;
    1513                                                                 ofstream *output = new ofstream(argv[argptr], ios::trunc);
    1514                                                                 if (!mol->OutputTemperatureFromTrajectories((ofstream *)&cout, 0, mol->MDSteps, output))
    1515                                                                         cout << Verbose(2) << "File could not be written." << endl;
    1516                                                                 else
    1517                                                                         cout << Verbose(2) << "File stored." << endl;
    1518                                                                 output->close();
    1519                                                                 delete(output);
    1520                                                                 argptr+=1;
    1521                                                         }
    1522                                                         break;
    1523                                                 case 'P':
    1524                                                         ExitFlag = 1;
    1525                                                         if ((argptr >= argc) || (argv[argptr][0] == '-')) {
    1526                                                                 ExitFlag = 255;
    1527                                                                 cerr << "Not enough or invalid arguments given for parsing and integrating forces: -P <forces file>" << endl;
    1528                                                         } else {
    1529                                                                 SaveFlag = true;
    1530                                                                 cout << Verbose(1) << "Parsing forces file and Verlet integrating." << endl;
    1531                                                                 if (!mol->VerletForceIntegration(argv[argptr], configuration.Deltat, configuration.GetIsAngstroem()))
    1532                                                                         cout << Verbose(2) << "File not found." << endl;
    1533                                                                 else
    1534                                                                         cout << Verbose(2) << "File found and parsed." << endl;
    1535                                                                 argptr+=1;
    1536                                                         }
    1537                                                         break;
     1227  Vector x,y,z,n;  // coordinates for absolute point in cell volume
     1228  double *factor; // unit factor if desired
     1229  ifstream test;
     1230  ofstream output;
     1231  string line;
     1232  atom *first;
     1233  bool SaveFlag = false;
     1234  int ExitFlag = 0;
     1235  int j;
     1236  double volume = 0.;
     1237  enum ConfigStatus config_present = absent;
     1238  clock_t start,end;
     1239  int argptr;
     1240  PathToDatabases = LocalPath;
     1241
     1242  // simply create a new molecule, wherein the config file is loaded and the manipulation takes place
     1243  molecule *mol = new molecule(periode);
     1244  molecules->insert(mol);
     1245
     1246  if (argc > 1) { // config file specified as option
     1247    // 1. : Parse options that just set variables or print help
     1248    argptr = 1;
     1249    do {
     1250      if (argv[argptr][0] == '-') {
     1251        cout << Verbose(0) << "Recognized command line argument: " << argv[argptr][1] << ".\n";
     1252        argptr++;
     1253        switch(argv[argptr-1][1]) {
     1254          case 'h':
     1255          case 'H':
     1256          case '?':
     1257            cout << "MoleCuilder suite" << endl << "==================" << endl << endl;
     1258            cout << "Usage: " << argv[0] << "[config file] [-{acefpsthH?vfrp}] [further arguments]" << endl;
     1259            cout << "or simply " << argv[0] << " without arguments for interactive session." << endl;
     1260            cout << "\t-a Z x1 x2 x3\tAdd new atom of element Z at coordinates (x1,x2,x3)." << endl;
     1261            cout << "\t-A <source>\tCreate adjacency list from bonds parsed from 'dbond'-style file." <<endl;
     1262            cout << "\t-b x1 x2 x3\tCenter atoms in domain with given edge lengths of (x1,x2,x3)." << endl;
     1263            cout << "\t-B <basis>\tSetting basis to store to MPQC config files." << endl;
     1264            cout << "\t-c x1 x2 x3\tCenter atoms in domain with a minimum distance to boundary of (x1,x2,x3)." << endl;
     1265            cout << "\t-D <bond distance>\tDepth-First-Search Analysis of the molecule, giving cycles and tree/back edges." << endl;
     1266            cout << "\t-O\tCenter atoms in origin." << endl;
     1267            cout << "\t-d x1 x2 x3\tDuplicate cell along each axis by given factor." << endl;
     1268            cout << "\t-e <file>\tSets the databases path to be parsed (default: ./)." << endl;
     1269            cout << "\t-E <id> <Z>\tChange atom <id>'s element to <Z>, <id> begins at 0." << endl;
     1270            cout << "\t-f/F <dist> <order>\tFragments the molecule in BOSSANOVA manner (with/out rings compressed) and stores config files in same dir as config (return code 0 - fragmented, 2 - no fragmentation necessary)." << endl;
     1271            cout << "\t-h/-H/-?\tGive this help screen." << endl;
     1272            cout << "\t-m <0/1>\tCalculate (0)/ Align in(1) PAS with greatest EV along z axis." << endl;
     1273            cout << "\t-n\tFast parsing (i.e. no trajectories are looked for)." << endl;
     1274            cout << "\t-N <radius> <file>\tGet non-convex-envelope." << endl;
     1275            cout << "\t-o <out>\tGet volume of the convex envelope (and store to tecplot file)." << endl;
     1276            cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl;
     1277            cout << "\t-P <file>\tParse given forces file and append as an MD step to config file via Verlet." << endl;
     1278            cout << "\t-r\t\tConvert file from an old pcp syntax." << endl;
     1279            cout << "\t-R\t\tRemove all atoms out of sphere around a given one." << endl;
     1280            cout << "\t-t x1 x2 x3\tTranslate all atoms by this vector (x1,x2,x3)." << endl;
     1281            cout << "\t-T <file> Store temperatures from the config file in <file>." << endl;
     1282            cout << "\t-s x1 x2 x3\tScale all atom coordinates by this vector (x1,x2,x3)." << endl;
     1283            cout << "\t-u rho\tsuspend in water solution and output necessary cell lengths, average density rho and repetition." << endl;
     1284            cout << "\t-v/-V\t\tGives version information." << endl;
     1285            cout << "Note: config files must not begin with '-' !" << endl;
     1286            delete(mol);
     1287            delete(periode);
     1288            return (1);
     1289            break;
     1290          case 'v':
     1291          case 'V':
     1292            cout << argv[0] << " " << VERSIONSTRING << endl;
     1293            cout << "Build your own molecule position set." << endl;
     1294            delete(mol);
     1295            delete(periode);
     1296            return (1);
     1297            break;
     1298          case 'e':
     1299            if ((argptr >= argc) || (argv[argptr][0] == '-')) {
     1300              cerr << "Not enough or invalid arguments for specifying element db: -e <db file>" << endl;
     1301            } else {
     1302              cout << "Using " << argv[argptr] << " as elements database." << endl;
     1303              PathToDatabases = argv[argptr];
     1304              argptr+=1;
     1305            }
     1306            break;
     1307          case 'n':
     1308            cout << "I won't parse trajectories." << endl;
     1309            configuration.FastParsing = true;
     1310            break;
     1311          default:  // no match? Step on
     1312            argptr++;
     1313            break;
     1314        }
     1315      } else
     1316        argptr++;
     1317    } while (argptr < argc);
     1318
     1319    // 2. Parse the element database
     1320    if (periode->LoadPeriodentafel(PathToDatabases)) {
     1321      cout << Verbose(0) << "Element list loaded successfully." << endl;
     1322      //periode->Output((ofstream *)&cout);
     1323    } else {
     1324      cout << Verbose(0) << "Element list loading failed." << endl;
     1325      return 1;
     1326    }
     1327    // 3. Find config file name and parse if possible
     1328    if (argv[1][0] != '-') {
     1329      cout << Verbose(0) << "Config file given." << endl;
     1330      test.open(argv[1], ios::in);
     1331      if (test == NULL) {
     1332        //return (1);
     1333        output.open(argv[1], ios::out);
     1334        if (output == NULL) {
     1335          cout << Verbose(1) << "Specified config file " << argv[1] << " not found." << endl;
     1336          config_present = absent;
     1337        } else {
     1338          cout << "Empty configuration file." << endl;
     1339          ConfigFileName = argv[1];
     1340          config_present = empty;
     1341          output.close();
     1342        }
     1343      } else {
     1344        test.close();
     1345        ConfigFileName = argv[1];
     1346        cout << Verbose(1) << "Specified config file found, parsing ... ";
     1347        switch (configuration.TestSyntax(ConfigFileName, periode, mol)) {
     1348          case 1:
     1349            cout << "new syntax." << endl;
     1350            configuration.Load(ConfigFileName, periode, mol);
     1351            config_present = present;
     1352            break;
     1353          case 0:
     1354            cout << "old syntax." << endl;
     1355            configuration.LoadOld(ConfigFileName, periode, mol);
     1356            config_present = present;
     1357            break;
     1358          default:
     1359            cout << "Unknown syntax or empty, yet present file." << endl;
     1360            config_present = empty;
     1361      }
     1362      }
     1363    } else
     1364      config_present = absent;
     1365    // 4. parse again through options, now for those depending on elements db and config presence
     1366    argptr = 1;
     1367    do {
     1368      cout << "Current Command line argument: " << argv[argptr] << "." << endl;
     1369      if (argv[argptr][0] == '-') {
     1370        argptr++;
     1371        if ((config_present == present) || (config_present == empty)) {
     1372          switch(argv[argptr-1][1]) {
     1373            case 'p':
     1374              ExitFlag = 1;
     1375              if ((argptr >= argc) || (argv[argptr][0] == '-')) {
     1376                ExitFlag = 255;
     1377                cerr << "Not enough arguments for parsing: -p <xyz file>" << endl;
     1378              } else {
     1379                SaveFlag = true;
     1380                cout << Verbose(1) << "Parsing xyz file for new atoms." << endl;
     1381                if (!mol->AddXYZFile(argv[argptr]))
     1382                  cout << Verbose(2) << "File not found." << endl;
     1383                else {
     1384                  cout << Verbose(2) << "File found and parsed." << endl;
     1385                  config_present = present;
     1386                }
     1387              }
     1388              break;
     1389            case 'a':
     1390              ExitFlag = 1;
     1391              if ((argptr >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr+1]))) {
     1392                ExitFlag = 255;
     1393                cerr << "Not enough or invalid arguments for adding atom: -a <element> <x> <y> <z>" << endl;
     1394              } else {
     1395                SaveFlag = true;
     1396                cout << Verbose(1) << "Adding new atom with element " << argv[argptr] << " at (" << argv[argptr+1] << "," << argv[argptr+2] << "," << argv[argptr+3] << "), ";
     1397                first = new atom;
     1398                first->type = periode->FindElement(atoi(argv[argptr]));
     1399                if (first->type != NULL)
     1400                  cout << Verbose(2) << "found element " << first->type->name << endl;
     1401                for (int i=NDIM;i--;)
     1402                  first->x.x[i] = atof(argv[argptr+1+i]);
     1403                if (first->type != NULL) {
     1404                  mol->AddAtom(first);  // add to molecule
     1405                  if ((config_present == empty) && (mol->AtomCount != 0))
     1406                    config_present = present;
     1407                } else
     1408                  cerr << Verbose(1) << "Could not find the specified element." << endl;
     1409                argptr+=4;
     1410              }
     1411              break;
     1412            default:  // no match? Don't step on (this is done in next switch's default)
     1413              break;
     1414          }
     1415        }
     1416        if (config_present == present) {
     1417          switch(argv[argptr-1][1]) {
     1418            case 'B':
     1419              if ((argptr >= argc) || (argv[argptr][0] == '-')) {
     1420                ExitFlag = 255;
     1421                cerr << "Not enough or invalid arguments given for setting MPQC basis: -B <basis name>" << endl;
     1422              } else {
     1423                configuration.basis = argv[argptr];
     1424                cout << Verbose(1) << "Setting MPQC basis to " << configuration.basis << "." << endl;
     1425                argptr+=1;
     1426              }
     1427              break;
     1428            case 'D':
     1429              ExitFlag = 1;
     1430              {
     1431                cout << Verbose(1) << "Depth-First-Search Analysis." << endl;
     1432                MoleculeLeafClass *Subgraphs = NULL;      // list of subgraphs from DFS analysis
     1433                int *MinimumRingSize = new int[mol->AtomCount];
     1434                atom ***ListOfLocalAtoms = NULL;
     1435                int FragmentCounter = 0;
     1436                class StackClass<bond *> *BackEdgeStack = NULL;
     1437                class StackClass<bond *> *LocalBackEdgeStack = NULL;
     1438                mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr]), configuration.GetIsAngstroem());
     1439                mol->CreateListOfBondsPerAtom((ofstream *)&cout);
     1440                Subgraphs = mol->DepthFirstSearchAnalysis((ofstream *)&cout, BackEdgeStack);
     1441                if (Subgraphs != NULL) {
     1442                  Subgraphs->next->FillBondStructureFromReference((ofstream *)&cout, mol, (FragmentCounter = 0), ListOfLocalAtoms, false);  // we want to keep the created ListOfLocalAtoms
     1443                  while (Subgraphs->next != NULL) {
     1444                    Subgraphs = Subgraphs->next;
     1445                    LocalBackEdgeStack = new StackClass<bond *> (Subgraphs->Leaf->BondCount);
     1446                    Subgraphs->Leaf->PickLocalBackEdges((ofstream *)&cout, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack);
     1447                    Subgraphs->Leaf->CyclicStructureAnalysis((ofstream *)&cout, BackEdgeStack, MinimumRingSize);
     1448                    delete(LocalBackEdgeStack);
     1449                    delete(Subgraphs->previous);
     1450                  }
     1451                  delete(Subgraphs);
     1452                  for (int i=0;i<FragmentCounter;i++)
     1453                    Free((void **)&ListOfLocalAtoms[FragmentCounter], "ParseCommandLineOptions: **ListOfLocalAtoms[]");
     1454                  Free((void **)&ListOfLocalAtoms, "ParseCommandLineOptions: ***ListOfLocalAtoms");
     1455                }
     1456                delete(BackEdgeStack);
     1457                delete[](MinimumRingSize);
     1458              }
     1459              //argptr+=1;
     1460              break;
     1461            case 'E':
     1462              ExitFlag = 1;
     1463              if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (argv[argptr+1][0] == '-')) {
     1464                ExitFlag = 255;
     1465                cerr << "Not enough or invalid arguments given for changing element: -E <atom nr.> <element>" << endl;
     1466              } else {
     1467                SaveFlag = true;
     1468                cout << Verbose(1) << "Changing atom " << argv[argptr] << " to element " << argv[argptr+1] << "." << endl;
     1469                first = mol->FindAtom(atoi(argv[argptr]));
     1470                first->type = periode->FindElement(atoi(argv[argptr+1]));
     1471                argptr+=2;
     1472              }
     1473              break;
     1474            case 'A':
     1475              ExitFlag = 1;
     1476              if ((argptr >= argc) || (argv[argptr][0] == '-')) {
     1477                ExitFlag =255;
     1478                cerr << "Missing source file for bonds in molecule: -A <bond sourcefile>" << endl;
     1479              } else {
     1480                cout << "Parsing bonds from " << argv[argptr] << "." << endl;
     1481                ifstream *input = new ifstream(argv[argptr]);
     1482                mol->CreateAdjacencyList2((ofstream *)&cout, input);
     1483                input->close();
     1484                argptr+=1;
     1485              }
     1486              break;
     1487            case 'N':
     1488              ExitFlag = 1;
     1489              if ((argptr+1 >= argc) || (argv[argptr+1][0] == '-')){
     1490                ExitFlag = 255;
     1491                cerr << "Not enough or invalid arguments given for non-convex envelope: -o <radius> <tecplot output file>" << endl;
     1492              } else {
     1493                class Tesselation T;
     1494                int N = 15;
     1495                int number = 100;
     1496                string filename(argv[argptr+1]);
     1497                filename.append(".csv");
     1498                cout << Verbose(0) << "Evaluating non-convex envelope.";
     1499                cout << Verbose(1) << "Using rolling ball of radius " << atof(argv[argptr]) << " and storing tecplot data in " << argv[argptr+1] << "." << endl;
     1500                LinkedCell LCList(mol, atof(argv[argptr]));    // \NOTE not twice the radius??
     1501                Find_non_convex_border((ofstream *)&cout, mol, &T, &LCList, argv[argptr+1], atof(argv[argptr]));
     1502                //FindDistributionOfEllipsoids((ofstream *)&cout, &T, &LCList, N, number, filename.c_str());
     1503                argptr+=2;
     1504              }
     1505              break;
     1506            case 'T':
     1507              ExitFlag = 1;
     1508              if ((argptr >= argc) || (argv[argptr][0] == '-')) {
     1509                ExitFlag = 255;
     1510                cerr << "Not enough or invalid arguments given for storing tempature: -T <temperature file>" << endl;
     1511              } else {
     1512                cout << Verbose(1) << "Storing temperatures in " << argv[argptr] << "." << endl;
     1513                ofstream *output = new ofstream(argv[argptr], ios::trunc);
     1514                if (!mol->OutputTemperatureFromTrajectories((ofstream *)&cout, 0, mol->MDSteps, output))
     1515                  cout << Verbose(2) << "File could not be written." << endl;
     1516                else
     1517                  cout << Verbose(2) << "File stored." << endl;
     1518                output->close();
     1519                delete(output);
     1520                argptr+=1;
     1521              }
     1522              break;
     1523            case 'P':
     1524              ExitFlag = 1;
     1525              if ((argptr >= argc) || (argv[argptr][0] == '-')) {
     1526                ExitFlag = 255;
     1527                cerr << "Not enough or invalid arguments given for parsing and integrating forces: -P <forces file>" << endl;
     1528              } else {
     1529                SaveFlag = true;
     1530                cout << Verbose(1) << "Parsing forces file and Verlet integrating." << endl;
     1531                if (!mol->VerletForceIntegration(argv[argptr], configuration.Deltat, configuration.GetIsAngstroem()))
     1532                  cout << Verbose(2) << "File not found." << endl;
     1533                else
     1534                  cout << Verbose(2) << "File found and parsed." << endl;
     1535                argptr+=1;
     1536              }
     1537              break;
    15381538            case 'R':
    15391539              ExitFlag = 1;
     
    15611561              }
    15621562              break;
    1563                                                 case 't':
    1564                                                         ExitFlag = 1;
    1565                                                         if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
    1566                                                                 ExitFlag = 255;
    1567                                                                 cerr << "Not enough or invalid arguments given for translation: -t <x> <y> <z>" << endl;
    1568                                                         } else {
    1569                                                                 ExitFlag = 1;
    1570                                                                 SaveFlag = true;
    1571                                                                 cout << Verbose(1) << "Translating all ions to new origin." << endl;
    1572                                                                 for (int i=NDIM;i--;)
    1573                                                                         x.x[i] = atof(argv[argptr+i]);
    1574                                                                 mol->Translate((const Vector *)&x);
    1575                                                                 argptr+=3;
    1576                                                         }
    1577                                                         break;
    1578                                                 case 's':
    1579                                                         ExitFlag = 1;
    1580                                                         if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) {
    1581                                                                 ExitFlag = 255;
    1582                                                                 cerr << "Not enough or invalid arguments given for scaling: -s <factor/[factor_x]> [factor_y] [factor_z]" << endl;
    1583                                                         } else {
    1584                                                                 SaveFlag = true;
    1585                                                                 j = -1;
    1586                                                                 cout << Verbose(1) << "Scaling all ion positions by factor." << endl;
    1587                                                                 factor = new double[NDIM];
    1588                                                                 factor[0] = atof(argv[argptr]);
    1589                                                                 if ((argptr < argc) && (IsValidNumber(argv[argptr])))
    1590                                                                         argptr++;
    1591                                                                 factor[1] = atof(argv[argptr]);
    1592                                                                 if ((argptr < argc) && (IsValidNumber(argv[argptr])))
    1593                                                                         argptr++;
    1594                                                                 factor[2] = atof(argv[argptr]);
    1595                                                                 mol->Scale(&factor);
    1596                                                                 for (int i=0;i<NDIM;i++) {
    1597                                                                         j += i+1;
    1598                                                                         x.x[i] = atof(argv[NDIM+i]);
    1599                                                                         mol->cell_size[j]*=factor[i];
    1600                                                                 }
    1601                                                                 delete[](factor);
    1602                                                                 argptr+=1;
    1603                                                         }
    1604                                                         break;
    1605                                                 case 'b':
    1606                                                         ExitFlag = 1;
    1607                                                         if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
    1608                                                                 ExitFlag = 255;
    1609                                                                 cerr << "Not enough or invalid arguments given for centering in box: -b <length_x> <length_y> <length_z>" << endl;
    1610                                                         } else {
    1611                                                                 SaveFlag = true;
    1612                                                                 j = -1;
    1613                                                                 cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl;
    1614                                                                 j=-1;
    1615                                                                 for (int i=0;i<NDIM;i++) {
    1616                                                                         j += i+1;
    1617                                                                         x.x[i] = atof(argv[argptr++]);
    1618                                                                         mol->cell_size[j] += x.x[i]*2.;
    1619                                                                 }
    1620                                                                 // center
    1621                                                                 mol->CenterInBox((ofstream *)&cout, &x);
    1622                                                                 // update Box of atoms by boundary
    1623                                                                 mol->SetBoxDimension(&x);
    1624                                                         }
    1625                                                         break;
    1626                                                 case 'c':
    1627                                                         ExitFlag = 1;
    1628                                                         if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
    1629                                                                 ExitFlag = 255;
    1630                                                                 cerr << "Not enough or invalid arguments given for centering with boundary: -c <boundary_x> <boundary_y> <boundary_z>" << endl;
    1631                                                         } else {
    1632                                                                 SaveFlag = true;
    1633                                                                 j = -1;
    1634                                                                 cout << Verbose(1) << "Centering atoms in config file within given additional boundary." << endl;
    1635                                                                 // make every coordinate positive
    1636                                                                 mol->CenterEdge((ofstream *)&cout, &x);
    1637                                                                 // update Box of atoms by boundary
    1638                                                                 mol->SetBoxDimension(&x);
    1639                                                                 // translate each coordinate by boundary
    1640                                                                 j=-1;
    1641                                                                 for (int i=0;i<NDIM;i++) {
    1642                                                                         j += i+1;
    1643                                                                         x.x[i] = atof(argv[argptr++]);
    1644                                                                         mol->cell_size[j] += x.x[i]*2.;
    1645                                                                 }
    1646                                                                 mol->Translate((const Vector *)&x);
    1647                                                         }
    1648                                                         break;
    1649                                                 case 'O':
    1650                                                         ExitFlag = 1;
    1651                                                         SaveFlag = true;
    1652                                                         cout << Verbose(1) << "Centering atoms in origin." << endl;
    1653                                                         mol->CenterOrigin((ofstream *)&cout, &x);
    1654                                                         mol->SetBoxDimension(&x);
    1655                                                         break;
    1656                                                 case 'r':
    1657                                                         ExitFlag = 1;
    1658                                                         SaveFlag = true;
    1659                                                         cout << Verbose(1) << "Converting config file from supposed old to new syntax." << endl;
    1660                                                         break;
    1661                                                 case 'F':
    1662                                                 case 'f':
    1663                                                         ExitFlag = 1;
    1664                                                         if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1]))) {
    1665                                                                 ExitFlag = 255;
    1666                                                                 cerr << "Not enough or invalid arguments for fragmentation: -f <max. bond distance> <bond order>" << endl;
    1667                                                         } else {
    1668                                                                 cout << "Fragmenting molecule with bond distance " << argv[argptr] << " angstroem, order of " << argv[argptr+1] << "." << endl;
    1669                                                                 cout << Verbose(0) << "Creating connection matrix..." << endl;
    1670                                                                 start = clock();
    1671                                                                 mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr++]), configuration.GetIsAngstroem());
    1672                                                                 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl;
    1673                                                                 if (mol->first->next != mol->last) {
    1674                                                                         ExitFlag = mol->FragmentMolecule((ofstream *)&cout, atoi(argv[argptr]), &configuration);
    1675                                                                 }
    1676                                                                 end = clock();
    1677                                                                 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
    1678                                                                 argptr+=2;
    1679                                                         }
    1680                                                         break;
    1681                                                 case 'm':
    1682                                                         ExitFlag = 1;
    1683                                                         j = atoi(argv[argptr++]);
    1684                                                         if ((j<0) || (j>1)) {
    1685                                                                 cerr << Verbose(1) << "ERROR: Argument of '-m' should be either 0 for no-rotate or 1 for rotate." << endl;
    1686                                                                 j = 0;
    1687                                                         }
    1688                                                         if (j) {
    1689                                                                 SaveFlag = true;
    1690                                                                 cout << Verbose(0) << "Converting to prinicipal axis system." << endl;
    1691                                                         } else
    1692                                                                 cout << Verbose(0) << "Evaluating prinicipal axis." << endl;
    1693                                                         mol->PrincipalAxisSystem((ofstream *)&cout, (bool)j);
    1694                                                         break;
    1695                                                 case 'o':
    1696                                                         ExitFlag = 1;
    1697                                                         if ((argptr >= argc) || (argv[argptr][0] == '-')){
    1698                                                                 ExitFlag = 255;
    1699                                                                 cerr << "Not enough or invalid arguments given for convex envelope: -o <tecplot output file>" << endl;
    1700                                                         } else {
    1701                                                                 cout << Verbose(0) << "Evaluating volume of the convex envelope.";
    1702                                                                 cout << Verbose(1) << "Storing tecplot data in " << argv[argptr] << "." << endl;
    1703                                                                 VolumeOfConvexEnvelope((ofstream *)&cout, argv[argptr], &configuration, NULL, mol);
    1704                                                                 argptr+=1;
    1705                                                         }
    1706                                                         break;
    1707                                                 case 'U':
    1708                                                         ExitFlag = 1;
    1709                                                         if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) ) {
    1710                                                                 ExitFlag = 255;
    1711                                                                 cerr << "Not enough or invalid arguments given for suspension with specified volume: -U <volume> <density>" << endl;
    1712                                                                 volume = -1; // for case 'u': don't print error again
    1713                                                         } else {
    1714                                                                 volume = atof(argv[argptr++]);
    1715                                                                 cout << Verbose(0) << "Using " << volume << " angstrom^3 as the volume instead of convex envelope one's." << endl;
    1716                                                         }
    1717                                                 case 'u':
    1718                                                         ExitFlag = 1;
    1719                                                         if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) {
    1720                                                                 if (volume != -1)
    1721                                                                         ExitFlag = 255;
    1722                                                                         cerr << "Not enough arguments given for suspension: -u <density>" << endl;
    1723                                                         } else {
    1724                                                                 double density;
    1725                                                                 SaveFlag = true;
    1726                                                                 cout << Verbose(0) << "Evaluating necessary cell volume for a cluster suspended in water.";
    1727                                                                 density = atof(argv[argptr++]);
    1728                                                                 if (density < 1.0) {
    1729                                                                         cerr << Verbose(0) << "Density must be greater than 1.0g/cm^3 !" << endl;
    1730                                                                         density = 1.3;
    1731                                                                 }
    1732 //                                                              for(int i=0;i<NDIM;i++) {
    1733 //                                                                      repetition[i] = atoi(argv[argptr++]);
    1734 //                                                                      if (repetition[i] < 1)
    1735 //                                                                              cerr << Verbose(0) << "ERROR: repetition value must be greater 1!" << endl;
    1736 //                                                                      repetition[i] = 1;
    1737 //                                                              }
    1738                                                                 PrepareClustersinWater((ofstream *)&cout, &configuration, mol, volume, density);        // if volume == 0, will calculate from ConvexEnvelope
    1739                                                         }
    1740                                                         break;
    1741                                                 case 'd':
    1742                                                         ExitFlag = 1;
    1743                                                         if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
    1744                                                                 ExitFlag = 255;
    1745                                                                 cerr << "Not enough or invalid arguments given for repeating cells: -d <repeat_x> <repeat_y> <repeat_z>" << endl;
    1746                                                         } else {
    1747                                                                 SaveFlag = true;
    1748                                                                 for (int axis = 1; axis <= NDIM; axis++) {
    1749                                                                         int faktor = atoi(argv[argptr++]);
    1750                                                                         int count;
    1751                                                                         element ** Elements;
    1752                                                                         Vector ** vectors;
    1753                                                                         if (faktor < 1) {
    1754                                                                                 cerr << Verbose(0) << "ERROR: Repetition faktor mus be greater than 1!" << endl;
    1755                                                                                 faktor = 1;
    1756                                                                         }
    1757                                                                         mol->CountAtoms((ofstream *)&cout);     // recount atoms
    1758                                                                         if (mol->AtomCount != 0) {      // if there is more than none
    1759                                                                                 count = mol->AtomCount; // is changed becausing of adding, thus has to be stored away beforehand
    1760                                                                                 Elements = new element *[count];
    1761                                                                                 vectors = new Vector *[count];
    1762                                                                                 j = 0;
    1763                                                                                 first = mol->start;
    1764                                                                                 while (first->next != mol->end) {       // make a list of all atoms with coordinates and element
    1765                                                                                         first = first->next;
    1766                                                                                         Elements[j] = first->type;
    1767                                                                                         vectors[j] = &first->x;
    1768                                                                                         j++;
    1769                                                                                 }
    1770                                                                                 if (count != j)
    1771                                                                                         cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl;
    1772                                                                                 x.Zero();
    1773                                                                                 y.Zero();
    1774                                                                                 y.x[abs(axis)-1] = mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] * abs(axis)/axis; // last term is for sign, first is for magnitude
    1775                                                                                 for (int i=1;i<faktor;i++) {    // then add this list with respective translation factor times
    1776                                                                                         x.AddVector(&y); // per factor one cell width further
    1777                                                                                         for (int k=count;k--;) { // go through every atom of the original cell
    1778                                                                                                 first = new atom(); // create a new body
    1779                                                                                                 first->x.CopyVector(vectors[k]);        // use coordinate of original atom
    1780                                                                                                 first->x.AddVector(&x);                 // translate the coordinates
    1781                                                                                                 first->type = Elements[k];      // insert original element
    1782                                                                                                 mol->AddAtom(first);                            // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...)
    1783                                                                                         }
    1784                                                                                 }
    1785                                                                                 // free memory
    1786                                                                                 delete[](Elements);
    1787                                                                                 delete[](vectors);
    1788                                                                                 // correct cell size
    1789                                                                                 if (axis < 0) { // if sign was negative, we have to translate everything
    1790                                                                                         x.Zero();
    1791                                                                                         x.AddVector(&y);
    1792                                                                                         x.Scale(-(faktor-1));
    1793                                                                                         mol->Translate(&x);
    1794                                                                                 }
    1795                                                                                 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor;
    1796                                                                         }
    1797                                                                 }
    1798                                                         }
    1799                                                         break;
    1800                                                 default:        // no match? Step on
    1801                                                         if ((argptr < argc) && (argv[argptr][0] != '-')) // if it started with a '-' we've already made a step!
    1802                                                                 argptr++;
    1803                                                         break;
    1804                                         }
    1805                                 }
    1806                         } else argptr++;
    1807                 } while (argptr < argc);
    1808                 if (SaveFlag)
    1809                         SaveConfig(ConfigFileName, &configuration, periode, molecules);
    1810                 if ((ExitFlag >= 1)) {
    1811                         delete(mol);
    1812                         delete(periode);
    1813                         return (ExitFlag);
    1814                 }
    1815         } else {        // no arguments, hence scan the elements db
    1816                 if (periode->LoadPeriodentafel(PathToDatabases))
    1817                         cout << Verbose(0) << "Element list loaded successfully." << endl;
    1818                 else
    1819                         cout << Verbose(0) << "Element list loading failed." << endl;
    1820                 configuration.RetrieveConfigPathAndName("main_pcp_linux");
    1821         }
    1822         return(0);
     1563            case 't':
     1564              ExitFlag = 1;
     1565              if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
     1566                ExitFlag = 255;
     1567                cerr << "Not enough or invalid arguments given for translation: -t <x> <y> <z>" << endl;
     1568              } else {
     1569                ExitFlag = 1;
     1570                SaveFlag = true;
     1571                cout << Verbose(1) << "Translating all ions to new origin." << endl;
     1572                for (int i=NDIM;i--;)
     1573                  x.x[i] = atof(argv[argptr+i]);
     1574                mol->Translate((const Vector *)&x);
     1575                argptr+=3;
     1576              }
     1577              break;
     1578            case 's':
     1579              ExitFlag = 1;
     1580              if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) {
     1581                ExitFlag = 255;
     1582                cerr << "Not enough or invalid arguments given for scaling: -s <factor/[factor_x]> [factor_y] [factor_z]" << endl;
     1583              } else {
     1584                SaveFlag = true;
     1585                j = -1;
     1586                cout << Verbose(1) << "Scaling all ion positions by factor." << endl;
     1587                factor = new double[NDIM];
     1588                factor[0] = atof(argv[argptr]);
     1589                if ((argptr < argc) && (IsValidNumber(argv[argptr])))
     1590                  argptr++;
     1591                factor[1] = atof(argv[argptr]);
     1592                if ((argptr < argc) && (IsValidNumber(argv[argptr])))
     1593                  argptr++;
     1594                factor[2] = atof(argv[argptr]);
     1595                mol->Scale(&factor);
     1596                for (int i=0;i<NDIM;i++) {
     1597                  j += i+1;
     1598                  x.x[i] = atof(argv[NDIM+i]);
     1599                  mol->cell_size[j]*=factor[i];
     1600                }
     1601                delete[](factor);
     1602                argptr+=1;
     1603              }
     1604              break;
     1605            case 'b':
     1606              ExitFlag = 1;
     1607              if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
     1608                ExitFlag = 255;
     1609                cerr << "Not enough or invalid arguments given for centering in box: -b <length_x> <length_y> <length_z>" << endl;
     1610              } else {
     1611                SaveFlag = true;
     1612                j = -1;
     1613                cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl;
     1614                j=-1;
     1615                for (int i=0;i<NDIM;i++) {
     1616                  j += i+1;
     1617                  x.x[i] = atof(argv[argptr++]);
     1618                  mol->cell_size[j] += x.x[i]*2.;
     1619                }
     1620                // center
     1621                mol->CenterInBox((ofstream *)&cout, &x);
     1622                // update Box of atoms by boundary
     1623                mol->SetBoxDimension(&x);
     1624              }
     1625              break;
     1626            case 'c':
     1627              ExitFlag = 1;
     1628              if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
     1629                ExitFlag = 255;
     1630                cerr << "Not enough or invalid arguments given for centering with boundary: -c <boundary_x> <boundary_y> <boundary_z>" << endl;
     1631              } else {
     1632                SaveFlag = true;
     1633                j = -1;
     1634                cout << Verbose(1) << "Centering atoms in config file within given additional boundary." << endl;
     1635                // make every coordinate positive
     1636                mol->CenterEdge((ofstream *)&cout, &x);
     1637                // update Box of atoms by boundary
     1638                mol->SetBoxDimension(&x);
     1639                // translate each coordinate by boundary
     1640                j=-1;
     1641                for (int i=0;i<NDIM;i++) {
     1642                  j += i+1;
     1643                  x.x[i] = atof(argv[argptr++]);
     1644                  mol->cell_size[j] += x.x[i]*2.;
     1645                }
     1646                mol->Translate((const Vector *)&x);
     1647              }
     1648              break;
     1649            case 'O':
     1650              ExitFlag = 1;
     1651              SaveFlag = true;
     1652              cout << Verbose(1) << "Centering atoms in origin." << endl;
     1653              mol->CenterOrigin((ofstream *)&cout, &x);
     1654              mol->SetBoxDimension(&x);
     1655              break;
     1656            case 'r':
     1657              ExitFlag = 1;
     1658              SaveFlag = true;
     1659              cout << Verbose(1) << "Converting config file from supposed old to new syntax." << endl;
     1660              break;
     1661            case 'F':
     1662            case 'f':
     1663              ExitFlag = 1;
     1664              if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1]))) {
     1665                ExitFlag = 255;
     1666                cerr << "Not enough or invalid arguments for fragmentation: -f <max. bond distance> <bond order>" << endl;
     1667              } else {
     1668                cout << "Fragmenting molecule with bond distance " << argv[argptr] << " angstroem, order of " << argv[argptr+1] << "." << endl;
     1669                cout << Verbose(0) << "Creating connection matrix..." << endl;
     1670                start = clock();
     1671                mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr++]), configuration.GetIsAngstroem());
     1672                cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl;
     1673                if (mol->first->next != mol->last) {
     1674                  ExitFlag = mol->FragmentMolecule((ofstream *)&cout, atoi(argv[argptr]), &configuration);
     1675                }
     1676                end = clock();
     1677                cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
     1678                argptr+=2;
     1679              }
     1680              break;
     1681            case 'm':
     1682              ExitFlag = 1;
     1683              j = atoi(argv[argptr++]);
     1684              if ((j<0) || (j>1)) {
     1685                cerr << Verbose(1) << "ERROR: Argument of '-m' should be either 0 for no-rotate or 1 for rotate." << endl;
     1686                j = 0;
     1687              }
     1688              if (j) {
     1689                SaveFlag = true;
     1690                cout << Verbose(0) << "Converting to prinicipal axis system." << endl;
     1691              } else
     1692                cout << Verbose(0) << "Evaluating prinicipal axis." << endl;
     1693              mol->PrincipalAxisSystem((ofstream *)&cout, (bool)j);
     1694              break;
     1695            case 'o':
     1696              ExitFlag = 1;
     1697              if ((argptr >= argc) || (argv[argptr][0] == '-')){
     1698                ExitFlag = 255;
     1699                cerr << "Not enough or invalid arguments given for convex envelope: -o <tecplot output file>" << endl;
     1700              } else {
     1701                cout << Verbose(0) << "Evaluating volume of the convex envelope.";
     1702                cout << Verbose(1) << "Storing tecplot data in " << argv[argptr] << "." << endl;
     1703                VolumeOfConvexEnvelope((ofstream *)&cout, argv[argptr], &configuration, NULL, mol);
     1704                argptr+=1;
     1705              }
     1706              break;
     1707            case 'U':
     1708              ExitFlag = 1;
     1709              if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) ) {
     1710                ExitFlag = 255;
     1711                cerr << "Not enough or invalid arguments given for suspension with specified volume: -U <volume> <density>" << endl;
     1712                volume = -1; // for case 'u': don't print error again
     1713              } else {
     1714                volume = atof(argv[argptr++]);
     1715                cout << Verbose(0) << "Using " << volume << " angstrom^3 as the volume instead of convex envelope one's." << endl;
     1716              }
     1717            case 'u':
     1718              ExitFlag = 1;
     1719              if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) {
     1720                if (volume != -1)
     1721                  ExitFlag = 255;
     1722                  cerr << "Not enough arguments given for suspension: -u <density>" << endl;
     1723              } else {
     1724                double density;
     1725                SaveFlag = true;
     1726                cout << Verbose(0) << "Evaluating necessary cell volume for a cluster suspended in water.";
     1727                density = atof(argv[argptr++]);
     1728                if (density < 1.0) {
     1729                  cerr << Verbose(0) << "Density must be greater than 1.0g/cm^3 !" << endl;
     1730                  density = 1.3;
     1731                }
     1732//                for(int i=0;i<NDIM;i++) {
     1733//                  repetition[i] = atoi(argv[argptr++]);
     1734//                  if (repetition[i] < 1)
     1735//                    cerr << Verbose(0) << "ERROR: repetition value must be greater 1!" << endl;
     1736//                  repetition[i] = 1;
     1737//                }
     1738                PrepareClustersinWater((ofstream *)&cout, &configuration, mol, volume, density);  // if volume == 0, will calculate from ConvexEnvelope
     1739              }
     1740              break;
     1741            case 'd':
     1742              ExitFlag = 1;
     1743              if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
     1744                ExitFlag = 255;
     1745                cerr << "Not enough or invalid arguments given for repeating cells: -d <repeat_x> <repeat_y> <repeat_z>" << endl;
     1746              } else {
     1747                SaveFlag = true;
     1748                for (int axis = 1; axis <= NDIM; axis++) {
     1749                  int faktor = atoi(argv[argptr++]);
     1750                  int count;
     1751                  element ** Elements;
     1752                  Vector ** vectors;
     1753                  if (faktor < 1) {
     1754                    cerr << Verbose(0) << "ERROR: Repetition faktor mus be greater than 1!" << endl;
     1755                    faktor = 1;
     1756                  }
     1757                  mol->CountAtoms((ofstream *)&cout);  // recount atoms
     1758                  if (mol->AtomCount != 0) {  // if there is more than none
     1759                    count = mol->AtomCount;  // is changed becausing of adding, thus has to be stored away beforehand
     1760                    Elements = new element *[count];
     1761                    vectors = new Vector *[count];
     1762                    j = 0;
     1763                    first = mol->start;
     1764                    while (first->next != mol->end) {  // make a list of all atoms with coordinates and element
     1765                      first = first->next;
     1766                      Elements[j] = first->type;
     1767                      vectors[j] = &first->x;
     1768                      j++;
     1769                    }
     1770                    if (count != j)
     1771                      cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl;
     1772                    x.Zero();
     1773                    y.Zero();
     1774                    y.x[abs(axis)-1] = mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] * abs(axis)/axis; // last term is for sign, first is for magnitude
     1775                    for (int i=1;i<faktor;i++) {  // then add this list with respective translation factor times
     1776                      x.AddVector(&y); // per factor one cell width further
     1777                      for (int k=count;k--;) { // go through every atom of the original cell
     1778                        first = new atom(); // create a new body
     1779                        first->x.CopyVector(vectors[k]);  // use coordinate of original atom
     1780                        first->x.AddVector(&x);      // translate the coordinates
     1781                        first->type = Elements[k];  // insert original element
     1782                        mol->AddAtom(first);        // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...)
     1783                      }
     1784                    }
     1785                    // free memory
     1786                    delete[](Elements);
     1787                    delete[](vectors);
     1788                    // correct cell size
     1789                    if (axis < 0) { // if sign was negative, we have to translate everything
     1790                      x.Zero();
     1791                      x.AddVector(&y);
     1792                      x.Scale(-(faktor-1));
     1793                      mol->Translate(&x);
     1794                    }
     1795                    mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor;
     1796                  }
     1797                }
     1798              }
     1799              break;
     1800            default:  // no match? Step on
     1801              if ((argptr < argc) && (argv[argptr][0] != '-')) // if it started with a '-' we've already made a step!
     1802                argptr++;
     1803              break;
     1804          }
     1805        }
     1806      } else argptr++;
     1807    } while (argptr < argc);
     1808    if (SaveFlag)
     1809      SaveConfig(ConfigFileName, &configuration, periode, molecules);
     1810    if ((ExitFlag >= 1)) {
     1811      delete(mol);
     1812      delete(periode);
     1813      return (ExitFlag);
     1814    }
     1815  } else {  // no arguments, hence scan the elements db
     1816    if (periode->LoadPeriodentafel(PathToDatabases))
     1817      cout << Verbose(0) << "Element list loaded successfully." << endl;
     1818    else
     1819      cout << Verbose(0) << "Element list loading failed." << endl;
     1820    configuration.RetrieveConfigPathAndName("main_pcp_linux");
     1821  }
     1822  return(0);
    18231823};
    18241824
     
    18271827int main(int argc, char **argv)
    18281828{
    1829         periodentafel *periode = new periodentafel; // and a period table of all elements
    1830         MoleculeListClass *molecules = new MoleculeListClass;  // list of all molecules
    1831         molecule *mol = NULL;
    1832         config configuration;
    1833         double tmp1;
    1834         atom *first, *second;
    1835         char choice;    // menu choice char
    1836         Vector x,y,z,n; // coordinates for absolute point in cell volume
    1837         bool valid; // flag if input was valid or not
    1838         ifstream test;
    1839         ofstream output;
    1840         string line;
    1841         char *ConfigFileName = NULL;
    1842         char *ElementsFileName = NULL;
    1843         int Z;
    1844         int j, axis, count, faktor;
    1845 
    1846         // =========================== PARSE COMMAND LINE OPTIONS ====================================
    1847         j = ParseCommandLineOptions(argc, argv, molecules, periode, configuration, ConfigFileName, ElementsFileName);
    1848         if (j == 1) return 0; // just for -v and -h options
    1849         if (j) return j;        // something went wrong
    1850 
    1851         // General stuff
    1852         if (molecules->ListOfMolecules.size() == 0) {
     1829  periodentafel *periode = new periodentafel; // and a period table of all elements
     1830  MoleculeListClass *molecules = new MoleculeListClass;  // list of all molecules
     1831  molecule *mol = NULL;
     1832  config configuration;
     1833  double tmp1;
     1834  atom *first, *second;
     1835  char choice;  // menu choice char
     1836  Vector x,y,z,n;  // coordinates for absolute point in cell volume
     1837  bool valid; // flag if input was valid or not
     1838  ifstream test;
     1839  ofstream output;
     1840  string line;
     1841  char *ConfigFileName = NULL;
     1842  char *ElementsFileName = NULL;
     1843  int Z;
     1844  int j, axis, count, faktor;
     1845
     1846  // =========================== PARSE COMMAND LINE OPTIONS ====================================
     1847  j = ParseCommandLineOptions(argc, argv, molecules, periode, configuration, ConfigFileName, ElementsFileName);
     1848  if (j == 1) return 0; // just for -v and -h options
     1849  if (j) return j;  // something went wrong
     1850
     1851  // General stuff
     1852  if (molecules->ListOfMolecules.size() == 0) {
    18531853    mol = new molecule(periode);
    18541854    if (mol->cell_size[0] == 0.) {
     
    18601860    }
    18611861    molecules->insert(mol);
    1862         }
    1863 
    1864         // =========================== START INTERACTIVE SESSION ====================================
    1865 
    1866         // now the main construction loop
    1867         cout << Verbose(0) << endl << "Now comes the real construction..." << endl;
    1868         do {
    1869                 cout << Verbose(0) << endl << endl;
    1870                 cout << Verbose(0) << "============Molecule list=======================" << endl;
    1871                 molecules->Enumerate((ofstream *)&cout);
    1872                 cout << Verbose(0) << "============Menu===============================" << endl;
     1862  }
     1863
     1864  // =========================== START INTERACTIVE SESSION ====================================
     1865
     1866  // now the main construction loop
     1867  cout << Verbose(0) << endl << "Now comes the real construction..." << endl;
     1868  do {
     1869    cout << Verbose(0) << endl << endl;
     1870    cout << Verbose(0) << "============Molecule list=======================" << endl;
     1871    molecules->Enumerate((ofstream *)&cout);
     1872    cout << Verbose(0) << "============Menu===============================" << endl;
    18731873    cout << Verbose(0) << "a - set molecule (in)active" << endl;
    18741874    cout << Verbose(0) << "e - edit new molecules" << endl;
     
    18861886    cin >> choice;
    18871887
    1888                 switch (choice) {
    1889                         case 'a':  // (in)activate molecule
     1888    switch (choice) {
     1889      case 'a':  // (in)activate molecule
    18901890        {
    18911891          cout << "Enter index of molecule: ";
     
    18971897            (*ListRunner)->ActiveFlag = !(*ListRunner)->ActiveFlag;
    18981898        }
    1899                           break;
    1900 
    1901                         case 'c': // edit each field of the configuration
    1902                         configuration.Edit();
    1903                         break;
     1899        break;
     1900
     1901      case 'c': // edit each field of the configuration
     1902      configuration.Edit();
     1903      break;
    19041904
    19051905      case 'e': // create molecule
     
    19191919        break;
    19201920
    1921                         case 'q': // quit
    1922                                 break;
    1923 
    1924                         case 's': // save to config file
    1925                                 SaveConfig(ConfigFileName, &configuration, periode, molecules);
    1926                                 break;
    1927 
    1928                         case 'T':
    1929                                 testroutine(molecules);
    1930                                 break;
    1931 
    1932                         default:
    1933                           break;
    1934                 };
    1935         } while (choice != 'q');
    1936 
    1937         // save element data base
    1938         if (periode->StorePeriodentafel(ElementsFileName)) //ElementsFileName
    1939                 cout << Verbose(0) << "Saving of elements.db successful." << endl;
    1940         else
    1941                 cout << Verbose(0) << "Saving of elements.db failed." << endl;
    1942 
    1943         delete(molecules);
    1944         delete(periode);
    1945         return (0);
     1921      case 'q': // quit
     1922        break;
     1923
     1924      case 's': // save to config file
     1925        SaveConfig(ConfigFileName, &configuration, periode, molecules);
     1926        break;
     1927
     1928      case 'T':
     1929        testroutine(molecules);
     1930        break;
     1931
     1932      default:
     1933        break;
     1934    };
     1935  } while (choice != 'q');
     1936
     1937  // save element data base
     1938  if (periode->StorePeriodentafel(ElementsFileName)) //ElementsFileName
     1939    cout << Verbose(0) << "Saving of elements.db successful." << endl;
     1940  else
     1941    cout << Verbose(0) << "Saving of elements.db failed." << endl;
     1942
     1943  delete(molecules);
     1944  delete(periode);
     1945  return (0);
    19461946}
    19471947
  • src/molecules.cpp

    ra5b2c3a r375b458  
    1616double LSQ (const gsl_vector * x, void * params)
    1717{
    18         double sum = 0.;
    19         struct LSQ_params *par = (struct LSQ_params *)params;
    20         Vector **vectors = par->vectors;
    21         int num = par->num;
    22 
    23         for (int i=num;i--;) {
    24                 for(int j=NDIM;j--;)
    25                         sum += (gsl_vector_get(x,j) - (vectors[i])->x[j])*(gsl_vector_get(x,j) - (vectors[i])->x[j]);
    26         }
    27 
    28         return sum;
     18  double sum = 0.;
     19  struct LSQ_params *par = (struct LSQ_params *)params;
     20  Vector **vectors = par->vectors;
     21  int num = par->num;
     22
     23  for (int i=num;i--;) {
     24    for(int j=NDIM;j--;)
     25      sum += (gsl_vector_get(x,j) - (vectors[i])->x[j])*(gsl_vector_get(x,j) - (vectors[i])->x[j]);
     26  }
     27
     28  return sum;
    2929};
    3030
     
    3636molecule::molecule(periodentafel *teil)
    3737{
    38         // init atom chain list
    39         start = new atom;
    40         end = new atom;
    41         start->father = NULL;
    42         end->father = NULL;
    43         link(start,end);
    44         // init bond chain list
    45         first = new bond(start, end, 1, -1);
    46         last = new bond(start, end, 1, -1);
    47         link(first,last);
    48         // other stuff
    49         MDSteps = 0;
    50         last_atom = 0;
    51         elemente = teil;
    52         AtomCount = 0;
    53         BondCount = 0;
    54         NoNonBonds = 0;
    55         NoNonHydrogen = 0;
    56         NoCyclicBonds = 0;
    57         ListOfBondsPerAtom = NULL;
    58         NumberOfBondsPerAtom = NULL;
    59         ElementCount = 0;
    60         for(int i=MAX_ELEMENTS;i--;)
    61                 ElementsInMolecule[i] = 0;
    62         cell_size[0] = cell_size[2] = cell_size[5]= 20.;
    63         cell_size[1] = cell_size[3] = cell_size[4]= 0.;
    64         strcpy(name,"none");
     38  // init atom chain list
     39  start = new atom;
     40  end = new atom;
     41  start->father = NULL;
     42  end->father = NULL;
     43  link(start,end);
     44  // init bond chain list
     45  first = new bond(start, end, 1, -1);
     46  last = new bond(start, end, 1, -1);
     47  link(first,last);
     48  // other stuff
     49  MDSteps = 0;
     50  last_atom = 0;
     51  elemente = teil;
     52  AtomCount = 0;
     53  BondCount = 0;
     54  NoNonBonds = 0;
     55  NoNonHydrogen = 0;
     56  NoCyclicBonds = 0;
     57  ListOfBondsPerAtom = NULL;
     58  NumberOfBondsPerAtom = NULL;
     59  ElementCount = 0;
     60  for(int i=MAX_ELEMENTS;i--;)
     61    ElementsInMolecule[i] = 0;
     62  cell_size[0] = cell_size[2] = cell_size[5]= 20.;
     63  cell_size[1] = cell_size[3] = cell_size[4]= 0.;
     64  strcpy(name,"none");
    6565};
    6666
     
    7070molecule::~molecule()
    7171{
    72         if (ListOfBondsPerAtom != NULL)
    73                 for(int i=AtomCount;i--;)
    74                         Free((void **)&ListOfBondsPerAtom[i], "molecule::~molecule: ListOfBondsPerAtom[i]");
    75         Free((void **)&ListOfBondsPerAtom, "molecule::~molecule: ListOfBondsPerAtom");
    76         Free((void **)&NumberOfBondsPerAtom, "molecule::~molecule: NumberOfBondsPerAtom");
    77         CleanupMolecule();
    78         delete(first);
    79         delete(last);
    80         delete(end);
    81         delete(start);
     72  if (ListOfBondsPerAtom != NULL)
     73    for(int i=AtomCount;i--;)
     74      Free((void **)&ListOfBondsPerAtom[i], "molecule::~molecule: ListOfBondsPerAtom[i]");
     75  Free((void **)&ListOfBondsPerAtom, "molecule::~molecule: ListOfBondsPerAtom");
     76  Free((void **)&NumberOfBondsPerAtom, "molecule::~molecule: NumberOfBondsPerAtom");
     77  CleanupMolecule();
     78  delete(first);
     79  delete(last);
     80  delete(end);
     81  delete(start);
    8282};
    8383
     
    8989bool molecule::AddAtom(atom *pointer)
    9090{
    91         if (pointer != NULL) {
    92                 pointer->sort = &pointer->nr;
    93                 pointer->nr = last_atom++;      // increase number within molecule
    94                 AtomCount++;
    95                 if (pointer->type != NULL) {
    96                         if (ElementsInMolecule[pointer->type->Z] == 0)
    97                                 ElementCount++;
    98                         ElementsInMolecule[pointer->type->Z]++; // increase number of elements
    99                         if (pointer->type->Z != 1)
    100                                 NoNonHydrogen++;
    101                         if (pointer->Name == NULL) {
    102                                 Free((void **)&pointer->Name, "molecule::AddAtom: *pointer->Name");
    103                                 pointer->Name = (char *) Malloc(sizeof(char)*6, "molecule::AddAtom: *pointer->Name");
    104                                 sprintf(pointer->Name, "%2s%02d", pointer->type->symbol, pointer->nr+1);
    105                         }
    106                 }
    107                 return add(pointer, end);
    108         } else
    109                 return false;
     91  if (pointer != NULL) {
     92    pointer->sort = &pointer->nr;
     93    pointer->nr = last_atom++;  // increase number within molecule
     94    AtomCount++;
     95    if (pointer->type != NULL) {
     96      if (ElementsInMolecule[pointer->type->Z] == 0)
     97        ElementCount++;
     98      ElementsInMolecule[pointer->type->Z]++; // increase number of elements
     99      if (pointer->type->Z != 1)
     100        NoNonHydrogen++;
     101      if (pointer->Name == NULL) {
     102        Free((void **)&pointer->Name, "molecule::AddAtom: *pointer->Name");
     103        pointer->Name = (char *) Malloc(sizeof(char)*6, "molecule::AddAtom: *pointer->Name");
     104        sprintf(pointer->Name, "%2s%02d", pointer->type->symbol, pointer->nr+1);
     105      }
     106    }
     107    return add(pointer, end);
     108  } else
     109    return false;
    110110};
    111111
     
    117117atom * molecule::AddCopyAtom(atom *pointer)
    118118{
    119         if (pointer != NULL) {
    120                 atom *walker = new atom();
    121                 walker->type = pointer->type;   // copy element of atom
    122                 walker->x.CopyVector(&pointer->x); // copy coordination
    123                 walker->v.CopyVector(&pointer->v); // copy velocity
    124                 walker->FixedIon = pointer->FixedIon;
    125                 walker->sort = &walker->nr;
    126                 walker->nr = last_atom++;       // increase number within molecule
    127                 walker->father = pointer; //->GetTrueFather();
    128                 walker->Name = (char *) Malloc(sizeof(char)*strlen(pointer->Name)+1, "molecule::AddCopyAtom: *Name");
    129                 strcpy (walker->Name, pointer->Name);
    130                 add(walker, end);
    131                 if ((pointer->type != NULL) && (pointer->type->Z != 1))
    132                         NoNonHydrogen++;
    133                 AtomCount++;
    134                 return walker;
    135         } else
    136                 return NULL;
     119  if (pointer != NULL) {
     120    atom *walker = new atom();
     121    walker->type = pointer->type;  // copy element of atom
     122    walker->x.CopyVector(&pointer->x); // copy coordination
     123    walker->v.CopyVector(&pointer->v); // copy velocity
     124    walker->FixedIon = pointer->FixedIon;
     125    walker->sort = &walker->nr;
     126    walker->nr = last_atom++;  // increase number within molecule
     127    walker->father = pointer; //->GetTrueFather();
     128    walker->Name = (char *) Malloc(sizeof(char)*strlen(pointer->Name)+1, "molecule::AddCopyAtom: *Name");
     129    strcpy (walker->Name, pointer->Name);
     130    add(walker, end);
     131    if ((pointer->type != NULL) && (pointer->type->Z != 1))
     132      NoNonHydrogen++;
     133    AtomCount++;
     134    return walker;
     135  } else
     136    return NULL;
    137137};
    138138
     
    142142 * -# Single Bond: Simply add new atom with bond distance rescaled to typical hydrogen one
    143143 * -# Double Bond: Here, we need the **BondList of the \a *origin atom, by scanning for the other bonds instead of
    144  *              *Bond, we use the through these connected atoms to determine the plane they lie in, vector::MakeNormalvector().
    145  *              The orthonormal vector to this plane along with the vector in *Bond direction determines the plane the two
    146  *              replacing hydrogens shall lie in. Now, all remains to do is take the usual hydrogen double bond angle for the
    147  *              element of *origin and form the sin/cos admixture of both plane vectors for the new coordinates of the two
    148  *              hydrogens forming this angle with *origin.
     144 *    *Bond, we use the through these connected atoms to determine the plane they lie in, vector::MakeNormalvector().
     145 *    The orthonormal vector to this plane along with the vector in *Bond direction determines the plane the two
     146 *    replacing hydrogens shall lie in. Now, all remains to do is take the usual hydrogen double bond angle for the
     147 *    element of *origin and form the sin/cos admixture of both plane vectors for the new coordinates of the two
     148 *    hydrogens forming this angle with *origin.
    149149 * -# Triple Bond: The idea is to set up a tetraoid (C1-H1-H2-H3) (however the lengths \f$b\f$ of the sides of the base
    150  *              triangle formed by the to be added hydrogens are not equal to the typical bond distance \f$l\f$ but have to be
    151  *              determined from the typical angle \f$\alpha\f$ for a hydrogen triple connected to the element of *origin):
    152  *              We have the height \f$d\f$ as the vector in *Bond direction (from triangle C1-H1-H2).
    153  *              \f[ h = l \cdot \cos{\left (\frac{\alpha}{2} \right )} \qquad b = 2l \cdot \sin{\left (\frac{\alpha}{2} \right)} \quad \rightarrow \quad d = l \cdot \sqrt{\cos^2{\left (\frac{\alpha}{2} \right)}-\frac{1}{3}\cdot\sin^2{\left (\frac{\alpha}{2}\right )}}
    154  *              \f]
    155  *              vector::GetNormalvector() creates one orthonormal vector from this *Bond vector and vector::MakeNormalvector creates
    156  *              the third one from the former two vectors. The latter ones form the plane of the base triangle mentioned above.
    157  *              The lengths for these are \f$f\f$ and \f$g\f$ (from triangle H1-H2-(center of H1-H2-H3)) with knowledge that
    158  *              the median lines in an isosceles triangle meet in the center point with a ratio 2:1.
    159  *              \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2}
    160  *              \f]
    161  *              as the coordination of all three atoms in the coordinate system of these three vectors:
    162  *              \f$\pmatrix{d & f & 0}\f$, \f$\pmatrix{d & -0.5 \cdot f & g}\f$ and \f$\pmatrix{d & -0.5 \cdot f & -g}\f$.
     150 *    triangle formed by the to be added hydrogens are not equal to the typical bond distance \f$l\f$ but have to be
     151 *    determined from the typical angle \f$\alpha\f$ for a hydrogen triple connected to the element of *origin):
     152 *    We have the height \f$d\f$ as the vector in *Bond direction (from triangle C1-H1-H2).
     153 *    \f[ h = l \cdot \cos{\left (\frac{\alpha}{2} \right )} \qquad b = 2l \cdot \sin{\left (\frac{\alpha}{2} \right)} \quad \rightarrow \quad d = l \cdot \sqrt{\cos^2{\left (\frac{\alpha}{2} \right)}-\frac{1}{3}\cdot\sin^2{\left (\frac{\alpha}{2}\right )}}
     154 *    \f]
     155 *    vector::GetNormalvector() creates one orthonormal vector from this *Bond vector and vector::MakeNormalvector creates
     156 *    the third one from the former two vectors. The latter ones form the plane of the base triangle mentioned above.
     157 *    The lengths for these are \f$f\f$ and \f$g\f$ (from triangle H1-H2-(center of H1-H2-H3)) with knowledge that
     158 *    the median lines in an isosceles triangle meet in the center point with a ratio 2:1.
     159 *    \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2}
     160 *    \f]
     161 *    as the coordination of all three atoms in the coordinate system of these three vectors:
     162 *    \f$\pmatrix{d & f & 0}\f$, \f$\pmatrix{d & -0.5 \cdot f & g}\f$ and \f$\pmatrix{d & -0.5 \cdot f & -g}\f$.
    163163 *
    164164 * \param *out output stream for debugging
     
    168168 * \param *replacement pointer to the atom which shall be copied as a hydrogen atom in this molecule
    169169 * \param **BondList list of bonds \a *replacement has (necessary to determine plane for double and triple bonds)
    170  * \param NumBond       number of bonds in \a **BondList
     170 * \param NumBond  number of bonds in \a **BondList
    171171 * \param isAngstroem whether the coordination of the given atoms is in AtomicLength (false) or Angstrom(true)
    172172 * \return number of atoms added, if < bond::BondDegree then something went wrong
     
    175175bool molecule::AddHydrogenReplacementAtom(ofstream *out, bond *TopBond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem)
    176176{
    177         double bondlength;      // bond length of the bond to be replaced/cut
    178         double bondangle;       // bond angle of the bond to be replaced/cut
    179         double BondRescale;      // rescale value for the hydrogen bond length
    180         bool AllWentWell = true;                // flag gathering the boolean return value of molecule::AddAtom and other functions, as return value on exit
    181         bond *FirstBond = NULL, *SecondBond = NULL; // Other bonds in double bond case to determine "other" plane
    182         atom *FirstOtherAtom = NULL, *SecondOtherAtom = NULL, *ThirdOtherAtom = NULL; // pointer to hydrogen atoms to be added
    183         double b,l,d,f,g, alpha, factors[NDIM];         // hold temporary values in triple bond case for coordination determination
    184         Vector Orthovector1, Orthovector2;      // temporary vectors in coordination construction
    185         Vector InBondvector;            // vector in direction of *Bond
    186         bond *Binder = NULL;
    187         double *matrix;
    188 
    189 //      *out << Verbose(3) << "Begin of AddHydrogenReplacementAtom." << endl;
    190         // create vector in direction of bond
    191         InBondvector.CopyVector(&TopReplacement->x);
    192         InBondvector.SubtractVector(&TopOrigin->x);
    193         bondlength = InBondvector.Norm();
    194 
    195         // is greater than typical bond distance? Then we have to correct periodically
    196         // the problem is not the H being out of the box, but InBondvector have the wrong direction
    197         // due to TopReplacement or Origin being on the wrong side!
    198         if (bondlength > BondDistance) {
    199 //              *out << Verbose(4) << "InBondvector is: ";
    200 //              InBondvector.Output(out);
    201 //              *out << endl;
    202                 Orthovector1.Zero();
    203                 for (int i=NDIM;i--;) {
    204                         l = TopReplacement->x.x[i] - TopOrigin->x.x[i];
    205                         if (fabs(l) > BondDistance) { // is component greater than bond distance
    206                                 Orthovector1.x[i] = (l < 0) ? -1. : +1.;
    207                         } // (signs are correct, was tested!)
    208                 }
    209                 matrix = ReturnFullMatrixforSymmetric(cell_size);
    210                 Orthovector1.MatrixMultiplication(matrix);
    211                 InBondvector.SubtractVector(&Orthovector1); // subtract just the additional translation
    212                 Free((void **)&matrix, "molecule::AddHydrogenReplacementAtom: *matrix");
    213                 bondlength = InBondvector.Norm();
    214 //              *out << Verbose(4) << "Corrected InBondvector is now: ";
    215 //              InBondvector.Output(out);
    216 //              *out << endl;
    217         } // periodic correction finished
    218 
    219         InBondvector.Normalize();
    220         // get typical bond length and store as scale factor for later
    221         BondRescale = TopOrigin->type->HBondDistance[TopBond->BondDegree-1];
    222         if (BondRescale == -1) {
    223                 cerr << Verbose(3) << "ERROR: There is no typical hydrogen bond distance in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl;
    224                 return false;
    225                 BondRescale = bondlength;
    226         } else {
    227                 if (!IsAngstroem)
    228                         BondRescale /= (1.*AtomicLengthToAngstroem);
    229         }
    230 
    231         // discern single, double and triple bonds
    232         switch(TopBond->BondDegree) {
    233                 case 1:
    234                         FirstOtherAtom = new atom();            // new atom
    235                         FirstOtherAtom->type = elemente->FindElement(1);        // element is Hydrogen
    236                         FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
    237                         FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
    238                         if (TopReplacement->type->Z == 1) { // neither rescale nor replace if it's already hydrogen
    239                                 FirstOtherAtom->father = TopReplacement;
    240                                 BondRescale = bondlength;
    241                         } else {
    242                                 FirstOtherAtom->father = NULL;  // if we replace hydrogen, we mark it as our father, otherwise we are just an added hydrogen with no father
    243                         }
    244                         InBondvector.Scale(&BondRescale);        // rescale the distance vector to Hydrogen bond length
    245                         FirstOtherAtom->x.CopyVector(&TopOrigin->x); // set coordination to origin ...
    246                         FirstOtherAtom->x.AddVector(&InBondvector);     // ... and add distance vector to replacement atom
    247                         AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
    248 //                      *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
    249 //                      FirstOtherAtom->x.Output(out);
    250 //                      *out << endl;
    251                         Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);
    252                         Binder->Cyclic = false;
    253                         Binder->Type = TreeEdge;
    254                         break;
    255                 case 2:
    256                         // determine two other bonds (warning if there are more than two other) plus valence sanity check
    257                         for (int i=0;i<NumBond;i++) {
    258                                 if (BondList[i] != TopBond) {
    259                                         if (FirstBond == NULL) {
    260                                                 FirstBond = BondList[i];
    261                                                 FirstOtherAtom = BondList[i]->GetOtherAtom(TopOrigin);
    262                                         } else if (SecondBond == NULL) {
    263                                                 SecondBond = BondList[i];
    264                                                 SecondOtherAtom = BondList[i]->GetOtherAtom(TopOrigin);
    265                                         } else {
    266                                                 *out << Verbose(3) << "WARNING: Detected more than four bonds for atom " << TopOrigin->Name;
    267                                         }
    268                                 }
    269                         }
    270                         if (SecondOtherAtom == NULL) {  // then we have an atom with valence four, but only 3 bonds: one to replace and one which is TopBond (third is FirstBond)
    271                                 SecondBond = TopBond;
    272                                 SecondOtherAtom = TopReplacement;
    273                         }
    274                         if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all
    275 //                              *out << Verbose(3) << "Regarding the double bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") to be constructed: Taking " << FirstOtherAtom->Name << " and " << SecondOtherAtom->Name << " along with " << TopOrigin->Name << " to determine orthogonal plane." << endl;
    276 
    277                                 // determine the plane of these two with the *origin
    278                                 AllWentWell = AllWentWell && Orthovector1.MakeNormalVector(&TopOrigin->x, &FirstOtherAtom->x, &SecondOtherAtom->x);
    279                         } else {
    280                                 Orthovector1.GetOneNormalVector(&InBondvector);
    281                         }
    282                         //*out << Verbose(3)<< "Orthovector1: ";
    283                         //Orthovector1.Output(out);
    284                         //*out << endl;
    285                         // orthogonal vector and bond vector between origin and replacement form the new plane
    286                         Orthovector1.MakeNormalVector(&InBondvector);
    287                         Orthovector1.Normalize();
    288                         //*out << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl;
    289 
    290                         // create the two Hydrogens ...
    291                         FirstOtherAtom = new atom();
    292                         SecondOtherAtom = new atom();
    293                         FirstOtherAtom->type = elemente->FindElement(1);
    294                         SecondOtherAtom->type = elemente->FindElement(1);
    295                         FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
    296                         FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
    297                         SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
    298                         SecondOtherAtom->FixedIon = TopReplacement->FixedIon;
    299                         FirstOtherAtom->father = NULL;  // we are just an added hydrogen with no father
    300                         SecondOtherAtom->father = NULL; //      we are just an added hydrogen with no father
    301                         bondangle = TopOrigin->type->HBondAngle[1];
    302                         if (bondangle == -1) {
    303                                 *out << Verbose(3) << "ERROR: There is no typical hydrogen bond angle in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl;
    304                                 return false;
    305                                 bondangle = 0;
    306                         }
    307                         bondangle *= M_PI/180./2.;
    308 //                      *out << Verbose(3) << "ReScaleCheck: InBondvector ";
    309 //                      InBondvector.Output(out);
    310 //                      *out << endl;
    311 //                      *out << Verbose(3) << "ReScaleCheck: Orthovector ";
    312 //                      Orthovector1.Output(out);
    313 //                      *out << endl;
    314 //                      *out << Verbose(3) << "Half the bond angle is " << bondangle << ", sin and cos of it: " << sin(bondangle) << ", " << cos(bondangle) << endl;
    315                         FirstOtherAtom->x.Zero();
    316                         SecondOtherAtom->x.Zero();
    317                         for(int i=NDIM;i--;) { // rotate by half the bond angle in both directions (InBondvector is bondangle = 0 direction)
    318                                 FirstOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (sin(bondangle));
    319                                 SecondOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (-sin(bondangle));
    320                         }
    321                         FirstOtherAtom->x.Scale(&BondRescale);  // rescale by correct BondDistance
    322                         SecondOtherAtom->x.Scale(&BondRescale);
    323                         //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl;
    324                         for(int i=NDIM;i--;) { // and make relative to origin atom
    325                                 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i];
    326                                 SecondOtherAtom->x.x[i] += TopOrigin->x.x[i];
    327                         }
    328                         // ... and add to molecule
    329                         AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
    330                         AllWentWell = AllWentWell && AddAtom(SecondOtherAtom);
    331 //                      *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
    332 //                      FirstOtherAtom->x.Output(out);
    333 //                      *out << endl;
    334 //                      *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: ";
    335 //                      SecondOtherAtom->x.Output(out);
    336 //                      *out << endl;
    337                         Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);
    338                         Binder->Cyclic = false;
    339                         Binder->Type = TreeEdge;
    340                         Binder = AddBond(BottomOrigin, SecondOtherAtom, 1);
    341                         Binder->Cyclic = false;
    342                         Binder->Type = TreeEdge;
    343                         break;
    344                 case 3:
    345                         // take the "usual" tetraoidal angle and add the three Hydrogen in direction of the bond (height of the tetraoid)
    346                         FirstOtherAtom = new atom();
    347                         SecondOtherAtom = new atom();
    348                         ThirdOtherAtom = new atom();
    349                         FirstOtherAtom->type = elemente->FindElement(1);
    350                         SecondOtherAtom->type = elemente->FindElement(1);
    351                         ThirdOtherAtom->type = elemente->FindElement(1);
    352                         FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
    353                         FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
    354                         SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
    355                         SecondOtherAtom->FixedIon = TopReplacement->FixedIon;
    356                         ThirdOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
    357                         ThirdOtherAtom->FixedIon = TopReplacement->FixedIon;
    358                         FirstOtherAtom->father = NULL;  //      we are just an added hydrogen with no father
    359                         SecondOtherAtom->father = NULL; //      we are just an added hydrogen with no father
    360                         ThirdOtherAtom->father = NULL;  //      we are just an added hydrogen with no father
    361 
    362                         // we need to vectors orthonormal the InBondvector
    363                         AllWentWell = AllWentWell && Orthovector1.GetOneNormalVector(&InBondvector);
    364 //                      *out << Verbose(3) << "Orthovector1: ";
    365 //                      Orthovector1.Output(out);
    366 //                      *out << endl;
    367                         AllWentWell = AllWentWell && Orthovector2.MakeNormalVector(&InBondvector, &Orthovector1);
    368 //                      *out << Verbose(3) << "Orthovector2: ";
    369 //                      Orthovector2.Output(out);
    370 //                      *out << endl;
    371 
    372                         // create correct coordination for the three atoms
    373                         alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.;  // retrieve triple bond angle from database
    374                         l = BondRescale;                                // desired bond length
    375                         b = 2.*l*sin(alpha);            // base length of isosceles triangle
    376                         d = l*sqrt(cos(alpha)*cos(alpha) - sin(alpha)*sin(alpha)/3.);    // length for InBondvector
    377                         f = b/sqrt(3.); // length for Orthvector1
    378                         g = b/2.;                                // length for Orthvector2
    379 //                      *out << Verbose(3) << "Bond length and half-angle: " << l << ", " << alpha << "\t (b,d,f,g) = " << b << ", " << d << ", " << f << ", " << g << ", " << endl;
    380 //                      *out << Verbose(3) << "The three Bond lengths: " << sqrt(d*d+f*f) << ", " << sqrt(d*d+(-0.5*f)*(-0.5*f)+g*g) << ", "    << sqrt(d*d+(-0.5*f)*(-0.5*f)+g*g) << endl;
    381                         factors[0] = d;
    382                         factors[1] = f;
    383                         factors[2] = 0.;
    384                         FirstOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);
    385                         factors[1] = -0.5*f;
    386                         factors[2] = g;
    387                         SecondOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);
    388                         factors[2] = -g;
    389                         ThirdOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);
    390 
    391                         // rescale each to correct BondDistance
    392 //                      FirstOtherAtom->x.Scale(&BondRescale);
    393 //                      SecondOtherAtom->x.Scale(&BondRescale);
    394 //                      ThirdOtherAtom->x.Scale(&BondRescale);
    395 
    396                         // and relative to *origin atom
    397                         FirstOtherAtom->x.AddVector(&TopOrigin->x);
    398                         SecondOtherAtom->x.AddVector(&TopOrigin->x);
    399                         ThirdOtherAtom->x.AddVector(&TopOrigin->x);
    400 
    401                         // ... and add to molecule
    402                         AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
    403                         AllWentWell = AllWentWell && AddAtom(SecondOtherAtom);
    404                         AllWentWell = AllWentWell && AddAtom(ThirdOtherAtom);
    405 //                      *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
    406 //                      FirstOtherAtom->x.Output(out);
    407 //                      *out << endl;
    408 //                      *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: ";
    409 //                      SecondOtherAtom->x.Output(out);
    410 //                      *out << endl;
    411 //                      *out << Verbose(4) << "Added " << *ThirdOtherAtom << " at: ";
    412 //                      ThirdOtherAtom->x.Output(out);
    413 //                      *out << endl;
    414                         Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);
    415                         Binder->Cyclic = false;
    416                         Binder->Type = TreeEdge;
    417                         Binder = AddBond(BottomOrigin, SecondOtherAtom, 1);
    418                         Binder->Cyclic = false;
    419                         Binder->Type = TreeEdge;
    420                         Binder = AddBond(BottomOrigin, ThirdOtherAtom, 1);
    421                         Binder->Cyclic = false;
    422                         Binder->Type = TreeEdge;
    423                         break;
    424                 default:
    425                         cerr << "ERROR: BondDegree does not state single, double or triple bond!" << endl;
    426                         AllWentWell = false;
    427                         break;
    428         }
    429 
    430 //      *out << Verbose(3) << "End of AddHydrogenReplacementAtom." << endl;
    431         return AllWentWell;
     177  double bondlength;  // bond length of the bond to be replaced/cut
     178  double bondangle;  // bond angle of the bond to be replaced/cut
     179  double BondRescale;  // rescale value for the hydrogen bond length
     180  bool AllWentWell = true;    // flag gathering the boolean return value of molecule::AddAtom and other functions, as return value on exit
     181  bond *FirstBond = NULL, *SecondBond = NULL; // Other bonds in double bond case to determine "other" plane
     182  atom *FirstOtherAtom = NULL, *SecondOtherAtom = NULL, *ThirdOtherAtom = NULL; // pointer to hydrogen atoms to be added
     183  double b,l,d,f,g, alpha, factors[NDIM];    // hold temporary values in triple bond case for coordination determination
     184  Vector Orthovector1, Orthovector2;  // temporary vectors in coordination construction
     185  Vector InBondvector;    // vector in direction of *Bond
     186  bond *Binder = NULL;
     187  double *matrix;
     188
     189//  *out << Verbose(3) << "Begin of AddHydrogenReplacementAtom." << endl;
     190  // create vector in direction of bond
     191  InBondvector.CopyVector(&TopReplacement->x);
     192  InBondvector.SubtractVector(&TopOrigin->x);
     193  bondlength = InBondvector.Norm();
     194
     195  // is greater than typical bond distance? Then we have to correct periodically
     196  // the problem is not the H being out of the box, but InBondvector have the wrong direction
     197  // due to TopReplacement or Origin being on the wrong side!
     198  if (bondlength > BondDistance) {
     199//    *out << Verbose(4) << "InBondvector is: ";
     200//    InBondvector.Output(out);
     201//    *out << endl;
     202    Orthovector1.Zero();
     203    for (int i=NDIM;i--;) {
     204      l = TopReplacement->x.x[i] - TopOrigin->x.x[i];
     205      if (fabs(l) > BondDistance) { // is component greater than bond distance
     206        Orthovector1.x[i] = (l < 0) ? -1. : +1.;
     207      } // (signs are correct, was tested!)
     208    }
     209    matrix = ReturnFullMatrixforSymmetric(cell_size);
     210    Orthovector1.MatrixMultiplication(matrix);
     211    InBondvector.SubtractVector(&Orthovector1); // subtract just the additional translation
     212    Free((void **)&matrix, "molecule::AddHydrogenReplacementAtom: *matrix");
     213    bondlength = InBondvector.Norm();
     214//    *out << Verbose(4) << "Corrected InBondvector is now: ";
     215//    InBondvector.Output(out);
     216//    *out << endl;
     217  } // periodic correction finished
     218
     219  InBondvector.Normalize();
     220  // get typical bond length and store as scale factor for later
     221  BondRescale = TopOrigin->type->HBondDistance[TopBond->BondDegree-1];
     222  if (BondRescale == -1) {
     223    cerr << Verbose(3) << "ERROR: There is no typical hydrogen bond distance in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl;
     224    return false;
     225    BondRescale = bondlength;
     226  } else {
     227    if (!IsAngstroem)
     228      BondRescale /= (1.*AtomicLengthToAngstroem);
     229  }
     230
     231  // discern single, double and triple bonds
     232  switch(TopBond->BondDegree) {
     233    case 1:
     234      FirstOtherAtom = new atom();    // new atom
     235      FirstOtherAtom->type = elemente->FindElement(1);  // element is Hydrogen
     236      FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
     237      FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
     238      if (TopReplacement->type->Z == 1) { // neither rescale nor replace if it's already hydrogen
     239        FirstOtherAtom->father = TopReplacement;
     240        BondRescale = bondlength;
     241      } else {
     242        FirstOtherAtom->father = NULL;  // if we replace hydrogen, we mark it as our father, otherwise we are just an added hydrogen with no father
     243      }
     244      InBondvector.Scale(&BondRescale);  // rescale the distance vector to Hydrogen bond length
     245      FirstOtherAtom->x.CopyVector(&TopOrigin->x); // set coordination to origin ...
     246      FirstOtherAtom->x.AddVector(&InBondvector);  // ... and add distance vector to replacement atom
     247      AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
     248//      *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
     249//      FirstOtherAtom->x.Output(out);
     250//      *out << endl;
     251      Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);
     252      Binder->Cyclic = false;
     253      Binder->Type = TreeEdge;
     254      break;
     255    case 2:
     256      // determine two other bonds (warning if there are more than two other) plus valence sanity check
     257      for (int i=0;i<NumBond;i++) {
     258        if (BondList[i] != TopBond) {
     259          if (FirstBond == NULL) {
     260            FirstBond = BondList[i];
     261            FirstOtherAtom = BondList[i]->GetOtherAtom(TopOrigin);
     262          } else if (SecondBond == NULL) {
     263            SecondBond = BondList[i];
     264            SecondOtherAtom = BondList[i]->GetOtherAtom(TopOrigin);
     265          } else {
     266            *out << Verbose(3) << "WARNING: Detected more than four bonds for atom " << TopOrigin->Name;
     267          }
     268        }
     269      }
     270      if (SecondOtherAtom == NULL) {  // then we have an atom with valence four, but only 3 bonds: one to replace and one which is TopBond (third is FirstBond)
     271        SecondBond = TopBond;
     272        SecondOtherAtom = TopReplacement;
     273      }
     274      if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all
     275//        *out << Verbose(3) << "Regarding the double bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") to be constructed: Taking " << FirstOtherAtom->Name << " and " << SecondOtherAtom->Name << " along with " << TopOrigin->Name << " to determine orthogonal plane." << endl;
     276
     277        // determine the plane of these two with the *origin
     278        AllWentWell = AllWentWell && Orthovector1.MakeNormalVector(&TopOrigin->x, &FirstOtherAtom->x, &SecondOtherAtom->x);
     279      } else {
     280        Orthovector1.GetOneNormalVector(&InBondvector);
     281      }
     282      //*out << Verbose(3)<< "Orthovector1: ";
     283      //Orthovector1.Output(out);
     284      //*out << endl;
     285      // orthogonal vector and bond vector between origin and replacement form the new plane
     286      Orthovector1.MakeNormalVector(&InBondvector);
     287      Orthovector1.Normalize();
     288      //*out << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl;
     289
     290      // create the two Hydrogens ...
     291      FirstOtherAtom = new atom();
     292      SecondOtherAtom = new atom();
     293      FirstOtherAtom->type = elemente->FindElement(1);
     294      SecondOtherAtom->type = elemente->FindElement(1);
     295      FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
     296      FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
     297      SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
     298      SecondOtherAtom->FixedIon = TopReplacement->FixedIon;
     299      FirstOtherAtom->father = NULL;  // we are just an added hydrogen with no father
     300      SecondOtherAtom->father = NULL;  //  we are just an added hydrogen with no father
     301      bondangle = TopOrigin->type->HBondAngle[1];
     302      if (bondangle == -1) {
     303        *out << Verbose(3) << "ERROR: There is no typical hydrogen bond angle in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl;
     304        return false;
     305        bondangle = 0;
     306      }
     307      bondangle *= M_PI/180./2.;
     308//      *out << Verbose(3) << "ReScaleCheck: InBondvector ";
     309//      InBondvector.Output(out);
     310//      *out << endl;
     311//      *out << Verbose(3) << "ReScaleCheck: Orthovector ";
     312//      Orthovector1.Output(out);
     313//      *out << endl;
     314//      *out << Verbose(3) << "Half the bond angle is " << bondangle << ", sin and cos of it: " << sin(bondangle) << ", " << cos(bondangle) << endl;
     315      FirstOtherAtom->x.Zero();
     316      SecondOtherAtom->x.Zero();
     317      for(int i=NDIM;i--;) { // rotate by half the bond angle in both directions (InBondvector is bondangle = 0 direction)
     318        FirstOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (sin(bondangle));
     319        SecondOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (-sin(bondangle));
     320      }
     321      FirstOtherAtom->x.Scale(&BondRescale);  // rescale by correct BondDistance
     322      SecondOtherAtom->x.Scale(&BondRescale);
     323      //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl;
     324      for(int i=NDIM;i--;) { // and make relative to origin atom
     325        FirstOtherAtom->x.x[i] += TopOrigin->x.x[i];
     326        SecondOtherAtom->x.x[i] += TopOrigin->x.x[i];
     327      }
     328      // ... and add to molecule
     329      AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
     330      AllWentWell = AllWentWell && AddAtom(SecondOtherAtom);
     331//      *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
     332//      FirstOtherAtom->x.Output(out);
     333//      *out << endl;
     334//      *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: ";
     335//      SecondOtherAtom->x.Output(out);
     336//      *out << endl;
     337      Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);
     338      Binder->Cyclic = false;
     339      Binder->Type = TreeEdge;
     340      Binder = AddBond(BottomOrigin, SecondOtherAtom, 1);
     341      Binder->Cyclic = false;
     342      Binder->Type = TreeEdge;
     343      break;
     344    case 3:
     345      // take the "usual" tetraoidal angle and add the three Hydrogen in direction of the bond (height of the tetraoid)
     346      FirstOtherAtom = new atom();
     347      SecondOtherAtom = new atom();
     348      ThirdOtherAtom = new atom();
     349      FirstOtherAtom->type = elemente->FindElement(1);
     350      SecondOtherAtom->type = elemente->FindElement(1);
     351      ThirdOtherAtom->type = elemente->FindElement(1);
     352      FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
     353      FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
     354      SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
     355      SecondOtherAtom->FixedIon = TopReplacement->FixedIon;
     356      ThirdOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
     357      ThirdOtherAtom->FixedIon = TopReplacement->FixedIon;
     358      FirstOtherAtom->father = NULL;  //  we are just an added hydrogen with no father
     359      SecondOtherAtom->father = NULL;  //  we are just an added hydrogen with no father
     360      ThirdOtherAtom->father = NULL;  //  we are just an added hydrogen with no father
     361
     362      // we need to vectors orthonormal the InBondvector
     363      AllWentWell = AllWentWell && Orthovector1.GetOneNormalVector(&InBondvector);
     364//      *out << Verbose(3) << "Orthovector1: ";
     365//      Orthovector1.Output(out);
     366//      *out << endl;
     367      AllWentWell = AllWentWell && Orthovector2.MakeNormalVector(&InBondvector, &Orthovector1);
     368//      *out << Verbose(3) << "Orthovector2: ";
     369//      Orthovector2.Output(out);
     370//      *out << endl;
     371
     372      // create correct coordination for the three atoms
     373      alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.;  // retrieve triple bond angle from database
     374      l = BondRescale;        // desired bond length
     375      b = 2.*l*sin(alpha);    // base length of isosceles triangle
     376      d = l*sqrt(cos(alpha)*cos(alpha) - sin(alpha)*sin(alpha)/3.);  // length for InBondvector
     377      f = b/sqrt(3.);  // length for Orthvector1
     378      g = b/2.;        // length for Orthvector2
     379//      *out << Verbose(3) << "Bond length and half-angle: " << l << ", " << alpha << "\t (b,d,f,g) = " << b << ", " << d << ", " << f << ", " << g << ", " << endl;
     380//      *out << Verbose(3) << "The three Bond lengths: " << sqrt(d*d+f*f) << ", " << sqrt(d*d+(-0.5*f)*(-0.5*f)+g*g) << ", "  << sqrt(d*d+(-0.5*f)*(-0.5*f)+g*g) << endl;
     381      factors[0] = d;
     382      factors[1] = f;
     383      factors[2] = 0.;
     384      FirstOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);
     385      factors[1] = -0.5*f;
     386      factors[2] = g;
     387      SecondOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);
     388      factors[2] = -g;
     389      ThirdOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);
     390
     391      // rescale each to correct BondDistance
     392//      FirstOtherAtom->x.Scale(&BondRescale);
     393//      SecondOtherAtom->x.Scale(&BondRescale);
     394//      ThirdOtherAtom->x.Scale(&BondRescale);
     395
     396      // and relative to *origin atom
     397      FirstOtherAtom->x.AddVector(&TopOrigin->x);
     398      SecondOtherAtom->x.AddVector(&TopOrigin->x);
     399      ThirdOtherAtom->x.AddVector(&TopOrigin->x);
     400
     401      // ... and add to molecule
     402      AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
     403      AllWentWell = AllWentWell && AddAtom(SecondOtherAtom);
     404      AllWentWell = AllWentWell && AddAtom(ThirdOtherAtom);
     405//      *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
     406//      FirstOtherAtom->x.Output(out);
     407//      *out << endl;
     408//      *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: ";
     409//      SecondOtherAtom->x.Output(out);
     410//      *out << endl;
     411//      *out << Verbose(4) << "Added " << *ThirdOtherAtom << " at: ";
     412//      ThirdOtherAtom->x.Output(out);
     413//      *out << endl;
     414      Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);
     415      Binder->Cyclic = false;
     416      Binder->Type = TreeEdge;
     417      Binder = AddBond(BottomOrigin, SecondOtherAtom, 1);
     418      Binder->Cyclic = false;
     419      Binder->Type = TreeEdge;
     420      Binder = AddBond(BottomOrigin, ThirdOtherAtom, 1);
     421      Binder->Cyclic = false;
     422      Binder->Type = TreeEdge;
     423      break;
     424    default:
     425      cerr << "ERROR: BondDegree does not state single, double or triple bond!" << endl;
     426      AllWentWell = false;
     427      break;
     428  }
     429
     430//  *out << Verbose(3) << "End of AddHydrogenReplacementAtom." << endl;
     431  return AllWentWell;
    432432};
    433433
     
    439439bool molecule::AddXYZFile(string filename)
    440440{
    441         istringstream *input = NULL;
    442         int NumberOfAtoms = 0; // atom number in xyz read
    443         int i, j; // loop variables
    444         atom *Walker = NULL;    // pointer to added atom
    445         char shorthand[3];      // shorthand for atom name
    446         ifstream xyzfile;        // xyz file
    447         string line;            // currently parsed line
    448         double x[3];            // atom coordinates
    449 
    450         xyzfile.open(filename.c_str());
    451         if (!xyzfile)
    452                 return false;
    453 
    454         getline(xyzfile,line,'\n'); // Read numer of atoms in file
    455         input = new istringstream(line);
    456         *input >> NumberOfAtoms;
    457         cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl;
    458         getline(xyzfile,line,'\n'); // Read comment
    459         cout << Verbose(1) << "Comment: " << line << endl;
    460 
    461         if (MDSteps == 0) // no atoms yet present
    462                 MDSteps++;
    463         for(i=0;i<NumberOfAtoms;i++){
    464                 Walker = new atom;
    465                 getline(xyzfile,line,'\n');
    466                 istringstream *item = new istringstream(line);
    467                 //istringstream input(line);
    468                 //cout << Verbose(1) << "Reading: " << line << endl;
    469                 *item >> shorthand;
    470                 *item >> x[0];
    471                 *item >> x[1];
    472                 *item >> x[2];
    473                 Walker->type = elemente->FindElement(shorthand);
    474                 if (Walker->type == NULL) {
    475                         cerr << "Could not parse the element at line: '" << line << "', setting to H.";
    476                         Walker->type = elemente->FindElement(1);
    477                 }
    478                 if (Trajectories[Walker].R.size() <= (unsigned int)MDSteps) {
    479                         Trajectories[Walker].R.resize(MDSteps+10);
    480                         Trajectories[Walker].U.resize(MDSteps+10);
    481                         Trajectories[Walker].F.resize(MDSteps+10);
    482                 }
    483                 for(j=NDIM;j--;) {
    484                         Walker->x.x[j] = x[j];
    485                         Trajectories[Walker].R.at(MDSteps-1).x[j] = x[j];
    486                         Trajectories[Walker].U.at(MDSteps-1).x[j] = 0;
    487                         Trajectories[Walker].F.at(MDSteps-1).x[j] = 0;
    488                 }
    489                 AddAtom(Walker);        // add to molecule
    490                 delete(item);
    491         }
    492         xyzfile.close();
    493         delete(input);
    494         return true;
     441  istringstream *input = NULL;
     442  int NumberOfAtoms = 0; // atom number in xyz read
     443  int i, j; // loop variables
     444  atom *Walker = NULL;  // pointer to added atom
     445  char shorthand[3];  // shorthand for atom name
     446  ifstream xyzfile;  // xyz file
     447  string line;    // currently parsed line
     448  double x[3];    // atom coordinates
     449
     450  xyzfile.open(filename.c_str());
     451  if (!xyzfile)
     452    return false;
     453
     454  getline(xyzfile,line,'\n'); // Read numer of atoms in file
     455  input = new istringstream(line);
     456  *input >> NumberOfAtoms;
     457  cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl;
     458  getline(xyzfile,line,'\n'); // Read comment
     459  cout << Verbose(1) << "Comment: " << line << endl;
     460
     461  if (MDSteps == 0) // no atoms yet present
     462    MDSteps++;
     463  for(i=0;i<NumberOfAtoms;i++){
     464    Walker = new atom;
     465    getline(xyzfile,line,'\n');
     466    istringstream *item = new istringstream(line);
     467    //istringstream input(line);
     468    //cout << Verbose(1) << "Reading: " << line << endl;
     469    *item >> shorthand;
     470    *item >> x[0];
     471    *item >> x[1];
     472    *item >> x[2];
     473    Walker->type = elemente->FindElement(shorthand);
     474    if (Walker->type == NULL) {
     475      cerr << "Could not parse the element at line: '" << line << "', setting to H.";
     476      Walker->type = elemente->FindElement(1);
     477    }
     478    if (Trajectories[Walker].R.size() <= (unsigned int)MDSteps) {
     479      Trajectories[Walker].R.resize(MDSteps+10);
     480      Trajectories[Walker].U.resize(MDSteps+10);
     481      Trajectories[Walker].F.resize(MDSteps+10);
     482    }
     483    for(j=NDIM;j--;) {
     484      Walker->x.x[j] = x[j];
     485      Trajectories[Walker].R.at(MDSteps-1).x[j] = x[j];
     486      Trajectories[Walker].U.at(MDSteps-1).x[j] = 0;
     487      Trajectories[Walker].F.at(MDSteps-1).x[j] = 0;
     488    }
     489    AddAtom(Walker);  // add to molecule
     490    delete(item);
     491  }
     492  xyzfile.close();
     493  delete(input);
     494  return true;
    495495};
    496496
     
    500500molecule *molecule::CopyMolecule()
    501501{
    502         molecule *copy = new molecule(elemente);
    503         atom *CurrentAtom = NULL;
    504         atom *LeftAtom = NULL, *RightAtom = NULL;
    505         atom *Walker = NULL;
    506 
    507         // copy all atoms
    508         Walker = start;
    509         while(Walker->next != end) {
    510                 Walker = Walker->next;
    511                 CurrentAtom = copy->AddCopyAtom(Walker);
    512         }
    513 
    514         // copy all bonds
    515         bond *Binder = first;
    516         bond *NewBond = NULL;
    517         while(Binder->next != last) {
    518                 Binder = Binder->next;
    519                 // get the pendant atoms of current bond in the copy molecule
    520                 LeftAtom = copy->start;
    521                 while (LeftAtom->next != copy->end) {
    522                         LeftAtom = LeftAtom->next;
    523                         if (LeftAtom->father == Binder->leftatom)
    524                                 break;
    525                 }
    526                 RightAtom = copy->start;
    527                 while (RightAtom->next != copy->end) {
    528                         RightAtom = RightAtom->next;
    529                         if (RightAtom->father == Binder->rightatom)
    530                                 break;
    531                 }
    532                 NewBond = copy->AddBond(LeftAtom, RightAtom, Binder->BondDegree);
    533                 NewBond->Cyclic = Binder->Cyclic;
    534                 if (Binder->Cyclic)
    535                         copy->NoCyclicBonds++;
    536                 NewBond->Type = Binder->Type;
    537         }
    538         // correct fathers
    539         Walker = copy->start;
    540         while(Walker->next != copy->end) {
    541                 Walker = Walker->next;
    542                 if (Walker->father->father == Walker->father)    // same atom in copy's father points to itself
    543                         Walker->father = Walker;        // set father to itself (copy of a whole molecule)
    544                 else
    545                  Walker->father = Walker->father->father;       // set father to original's father
    546         }
    547         // copy values
    548         copy->CountAtoms((ofstream *)&cout);
    549         copy->CountElements();
    550         if (first->next != last) {      // if adjaceny list is present
    551                 copy->BondDistance = BondDistance;
    552                 copy->CreateListOfBondsPerAtom((ofstream *)&cout);
    553         }
    554 
    555         return copy;
     502  molecule *copy = new molecule(elemente);
     503  atom *CurrentAtom = NULL;
     504  atom *LeftAtom = NULL, *RightAtom = NULL;
     505  atom *Walker = NULL;
     506
     507  // copy all atoms
     508  Walker = start;
     509  while(Walker->next != end) {
     510    Walker = Walker->next;
     511    CurrentAtom = copy->AddCopyAtom(Walker);
     512  }
     513
     514  // copy all bonds
     515  bond *Binder = first;
     516  bond *NewBond = NULL;
     517  while(Binder->next != last) {
     518    Binder = Binder->next;
     519    // get the pendant atoms of current bond in the copy molecule
     520    LeftAtom = copy->start;
     521    while (LeftAtom->next != copy->end) {
     522      LeftAtom = LeftAtom->next;
     523      if (LeftAtom->father == Binder->leftatom)
     524        break;
     525    }
     526    RightAtom = copy->start;
     527    while (RightAtom->next != copy->end) {
     528      RightAtom = RightAtom->next;
     529      if (RightAtom->father == Binder->rightatom)
     530        break;
     531    }
     532    NewBond = copy->AddBond(LeftAtom, RightAtom, Binder->BondDegree);
     533    NewBond->Cyclic = Binder->Cyclic;
     534    if (Binder->Cyclic)
     535      copy->NoCyclicBonds++;
     536    NewBond->Type = Binder->Type;
     537  }
     538  // correct fathers
     539  Walker = copy->start;
     540  while(Walker->next != copy->end) {
     541    Walker = Walker->next;
     542    if (Walker->father->father == Walker->father)  // same atom in copy's father points to itself
     543      Walker->father = Walker;  // set father to itself (copy of a whole molecule)
     544    else
     545     Walker->father = Walker->father->father;  // set father to original's father
     546  }
     547  // copy values
     548  copy->CountAtoms((ofstream *)&cout);
     549  copy->CountElements();
     550  if (first->next != last) {  // if adjaceny list is present
     551    copy->BondDistance = BondDistance;
     552    copy->CreateListOfBondsPerAtom((ofstream *)&cout);
     553  }
     554
     555  return copy;
    556556};
    557557
     
    564564bond * molecule::AddBond(atom *atom1, atom *atom2, int degree=1)
    565565{
    566         bond *Binder = NULL;
    567         if ((atom1 != NULL) && (FindAtom(atom1->nr) != NULL) && (atom2 != NULL) && (FindAtom(atom2->nr) != NULL)) {
    568                 Binder = new bond(atom1, atom2, degree, BondCount++);
    569                 if ((atom1->type != NULL) && (atom1->type->Z != 1) && (atom2->type != NULL) && (atom2->type->Z != 1))
    570                         NoNonBonds++;
    571                 add(Binder, last);
    572         } else {
    573                 cerr << Verbose(1) << "ERROR: Could not add bond between " << atom1->Name << " and " << atom2->Name << " as one or both are not present in the molecule." << endl;
    574         }
    575         return Binder;
     566  bond *Binder = NULL;
     567  if ((atom1 != NULL) && (FindAtom(atom1->nr) != NULL) && (atom2 != NULL) && (FindAtom(atom2->nr) != NULL)) {
     568    Binder = new bond(atom1, atom2, degree, BondCount++);
     569    if ((atom1->type != NULL) && (atom1->type->Z != 1) && (atom2->type != NULL) && (atom2->type->Z != 1))
     570      NoNonBonds++;
     571    add(Binder, last);
     572  } else {
     573    cerr << Verbose(1) << "ERROR: Could not add bond between " << atom1->Name << " and " << atom2->Name << " as one or both are not present in the molecule." << endl;
     574  }
     575  return Binder;
    576576};
    577577
     
    583583bool molecule::RemoveBond(bond *pointer)
    584584{
    585         //cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl;
    586         removewithoutcheck(pointer);
    587         return true;
     585  //cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl;
     586  removewithoutcheck(pointer);
     587  return true;
    588588};
    589589
     
    595595bool molecule::RemoveBonds(atom *BondPartner)
    596596{
    597         cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl;
    598         return false;
     597  cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl;
     598  return false;
    599599};
    600600
     
    619619void molecule::SetBoxDimension(Vector *dim)
    620620{
    621         cell_size[0] = dim->x[0];
    622         cell_size[1] = 0.;
    623         cell_size[2] = dim->x[1];
    624         cell_size[3] = 0.;
    625         cell_size[4] = 0.;
    626         cell_size[5] = dim->x[2];
     621  cell_size[0] = dim->x[0];
     622  cell_size[1] = 0.;
     623  cell_size[2] = dim->x[1];
     624  cell_size[3] = 0.;
     625  cell_size[4] = 0.;
     626  cell_size[5] = dim->x[2];
    627627};
    628628
     
    633633bool molecule::CenterInBox(ofstream *out, Vector *BoxLengths)
    634634{
    635         bool status = true;
    636         atom *ptr = NULL;
    637         Vector *min = new Vector;
    638         Vector *max = new Vector;
    639 
    640         // gather min and max for each axis
    641         ptr = start->next;      // start at first in list
    642         if (ptr != end) {        //list not empty?
    643                 for (int i=NDIM;i--;) {
    644                         max->x[i] = ptr->x.x[i];
    645                         min->x[i] = ptr->x.x[i];
    646                 }
    647                 while (ptr->next != end) {      // continue with second if present
    648                         ptr = ptr->next;
    649                         //ptr->Output(1,1,out);
    650                         for (int i=NDIM;i--;) {
    651                                 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i];
    652                                 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i];
    653                         }
    654                 }
    655         }
    656         // sanity check
    657         for(int i=NDIM;i--;) {
    658                 if (max->x[i] - min->x[i] > BoxLengths->x[i])
    659                         status = false;
    660         }
    661         // warn if check failed
    662         if (!status)
    663                 *out << "WARNING: molecule is bigger than defined box!" << endl;
    664         else {  // else center in box
    665                 max->AddVector(min);
    666                 max->Scale(-1.);
    667                 max->AddVector(BoxLengths);
    668                 max->Scale(0.5);
    669                 Translate(max);
    670         }
    671 
    672         // free and exit
    673         delete(min);
    674         delete(max);
    675         return status;
     635  bool status = true;
     636  atom *ptr = NULL;
     637  Vector *min = new Vector;
     638  Vector *max = new Vector;
     639
     640  // gather min and max for each axis
     641  ptr = start->next;  // start at first in list
     642  if (ptr != end) {  //list not empty?
     643    for (int i=NDIM;i--;) {
     644      max->x[i] = ptr->x.x[i];
     645      min->x[i] = ptr->x.x[i];
     646    }
     647    while (ptr->next != end) {  // continue with second if present
     648      ptr = ptr->next;
     649      //ptr->Output(1,1,out);
     650      for (int i=NDIM;i--;) {
     651        max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i];
     652        min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i];
     653      }
     654    }
     655  }
     656  // sanity check
     657  for(int i=NDIM;i--;) {
     658    if (max->x[i] - min->x[i] > BoxLengths->x[i])
     659      status = false;
     660  }
     661  // warn if check failed
     662  if (!status)
     663    *out << "WARNING: molecule is bigger than defined box!" << endl;
     664  else {  // else center in box
     665    max->AddVector(min);
     666    max->Scale(-1.);
     667    max->AddVector(BoxLengths);
     668    max->Scale(0.5);
     669    Translate(max);
     670  }
     671
     672  // free and exit
     673  delete(min);
     674  delete(max);
     675  return status;
    676676};
    677677
     
    682682void molecule::CenterEdge(ofstream *out, Vector *max)
    683683{
    684         Vector *min = new Vector;
    685 
    686 //      *out << Verbose(3) << "Begin of CenterEdge." << endl;
    687         atom *ptr = start->next;        // start at first in list
    688         if (ptr != end) {        //list not empty?
    689                 for (int i=NDIM;i--;) {
    690                         max->x[i] = ptr->x.x[i];
    691                         min->x[i] = ptr->x.x[i];
    692                 }
    693                 while (ptr->next != end) {      // continue with second if present
    694                         ptr = ptr->next;
    695                         //ptr->Output(1,1,out);
    696                         for (int i=NDIM;i--;) {
    697                                 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i];
    698                                 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i];
    699                         }
    700                 }
    701 //              *out << Verbose(4) << "Maximum is ";
    702 //              max->Output(out);
    703 //              *out << ", Minimum is ";
    704 //              min->Output(out);
    705 //              *out << endl;
    706                 min->Scale(-1.);
    707                 max->AddVector(min);
    708                 Translate(min);
    709         }
    710         delete(min);
    711 //      *out << Verbose(3) << "End of CenterEdge." << endl;
     684  Vector *min = new Vector;
     685
     686//  *out << Verbose(3) << "Begin of CenterEdge." << endl;
     687  atom *ptr = start->next;  // start at first in list
     688  if (ptr != end) {  //list not empty?
     689    for (int i=NDIM;i--;) {
     690      max->x[i] = ptr->x.x[i];
     691      min->x[i] = ptr->x.x[i];
     692    }
     693    while (ptr->next != end) {  // continue with second if present
     694      ptr = ptr->next;
     695      //ptr->Output(1,1,out);
     696      for (int i=NDIM;i--;) {
     697        max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i];
     698        min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i];
     699      }
     700    }
     701//    *out << Verbose(4) << "Maximum is ";
     702//    max->Output(out);
     703//    *out << ", Minimum is ";
     704//    min->Output(out);
     705//    *out << endl;
     706    min->Scale(-1.);
     707    max->AddVector(min);
     708    Translate(min);
     709  }
     710  delete(min);
     711//  *out << Verbose(3) << "End of CenterEdge." << endl;
    712712};
    713713
     
    718718void molecule::CenterOrigin(ofstream *out, Vector *center)
    719719{
    720         int Num = 0;
    721         atom *ptr = start->next;        // start at first in list
    722 
    723         for(int i=NDIM;i--;) // zero center vector
    724                 center->x[i] = 0.;
    725 
    726         if (ptr != end) {        //list not empty?
    727                 while (ptr->next != end) {      // continue with second if present
    728                         ptr = ptr->next;
    729                         Num++;
    730                         center->AddVector(&ptr->x);
    731                 }
    732                 center->Scale(-1./Num); // divide through total number (and sign for direction)
    733                 Translate(center);
    734         }
     720  int Num = 0;
     721  atom *ptr = start->next;  // start at first in list
     722
     723  for(int i=NDIM;i--;) // zero center vector
     724    center->x[i] = 0.;
     725
     726  if (ptr != end) {  //list not empty?
     727    while (ptr->next != end) {  // continue with second if present
     728      ptr = ptr->next;
     729      Num++;
     730      center->AddVector(&ptr->x);
     731    }
     732    center->Scale(-1./Num); // divide through total number (and sign for direction)
     733    Translate(center);
     734  }
    735735};
    736736
     
    741741Vector * molecule::DetermineCenterOfAll(ofstream *out)
    742742{
    743         atom *ptr = start->next;        // start at first in list
    744         Vector *a = new Vector();
    745         Vector tmp;
    746         double Num = 0;
    747 
    748         a->Zero();
    749 
    750         if (ptr != end) {        //list not empty?
    751                 while (ptr->next != end) {      // continue with second if present
    752                         ptr = ptr->next;
    753                         Num += 1.;
    754                         tmp.CopyVector(&ptr->x);
    755                         a->AddVector(&tmp);
    756                 }
    757                 a->Scale(-1./Num); // divide through total mass (and sign for direction)
    758         }
    759         //cout << Verbose(1) << "Resulting center of gravity: ";
    760         //a->Output(out);
    761         //cout << endl;
    762         return a;
     743  atom *ptr = start->next;  // start at first in list
     744  Vector *a = new Vector();
     745  Vector tmp;
     746  double Num = 0;
     747
     748  a->Zero();
     749
     750  if (ptr != end) {  //list not empty?
     751    while (ptr->next != end) {  // continue with second if present
     752      ptr = ptr->next;
     753      Num += 1.;
     754      tmp.CopyVector(&ptr->x);
     755      a->AddVector(&tmp);
     756    }
     757    a->Scale(-1./Num); // divide through total mass (and sign for direction)
     758  }
     759  //cout << Verbose(1) << "Resulting center of gravity: ";
     760  //a->Output(out);
     761  //cout << endl;
     762  return a;
    763763};
    764764
     
    769769Vector * molecule::DetermineCenterOfGravity(ofstream *out)
    770770{
    771         atom *ptr = start->next;        // start at first in list
    772         Vector *a = new Vector();
    773         Vector tmp;
    774         double Num = 0;
    775 
    776         a->Zero();
    777 
    778         if (ptr != end) {        //list not empty?
    779                 while (ptr->next != end) {      // continue with second if present
    780                         ptr = ptr->next;
    781                         Num += ptr->type->mass;
    782                         tmp.CopyVector(&ptr->x);
    783                         tmp.Scale(ptr->type->mass);     // scale by mass
    784                         a->AddVector(&tmp);
    785                 }
    786                 a->Scale(-1./Num); // divide through total mass (and sign for direction)
    787         }
    788 //      *out << Verbose(1) << "Resulting center of gravity: ";
    789 //      a->Output(out);
    790 //      *out << endl;
    791         return a;
     771  atom *ptr = start->next;  // start at first in list
     772  Vector *a = new Vector();
     773  Vector tmp;
     774  double Num = 0;
     775
     776  a->Zero();
     777
     778  if (ptr != end) {  //list not empty?
     779    while (ptr->next != end) {  // continue with second if present
     780      ptr = ptr->next;
     781      Num += ptr->type->mass;
     782      tmp.CopyVector(&ptr->x);
     783      tmp.Scale(ptr->type->mass);  // scale by mass
     784      a->AddVector(&tmp);
     785    }
     786    a->Scale(-1./Num); // divide through total mass (and sign for direction)
     787  }
     788//  *out << Verbose(1) << "Resulting center of gravity: ";
     789//  a->Output(out);
     790//  *out << endl;
     791  return a;
    792792};
    793793
     
    798798void molecule::CenterGravity(ofstream *out, Vector *center)
    799799{
    800         if (center == NULL) {
    801                 DetermineCenter(*center);
    802                 Translate(center);
    803                 delete(center);
    804         } else {
    805                 Translate(center);
    806         }
     800  if (center == NULL) {
     801    DetermineCenter(*center);
     802    Translate(center);
     803    delete(center);
     804  } else {
     805    Translate(center);
     806  }
    807807};
    808808
     
    812812void molecule::Scale(double **factor)
    813813{
    814         atom *ptr = start;
    815 
    816         while (ptr->next != end) {
    817                 ptr = ptr->next;
    818                 for (int j=0;j<MDSteps;j++)
    819                         Trajectories[ptr].R.at(j).Scale(factor);
    820                 ptr->x.Scale(factor);
    821         }
     814  atom *ptr = start;
     815
     816  while (ptr->next != end) {
     817    ptr = ptr->next;
     818    for (int j=0;j<MDSteps;j++)
     819      Trajectories[ptr].R.at(j).Scale(factor);
     820    ptr->x.Scale(factor);
     821  }
    822822};
    823823
     
    827827void molecule::Translate(const Vector *trans)
    828828{
    829         atom *ptr = start;
    830 
    831         while (ptr->next != end) {
    832                 ptr = ptr->next;
    833                 for (int j=0;j<MDSteps;j++)
    834                         Trajectories[ptr].R.at(j).Translate(trans);
    835                 ptr->x.Translate(trans);
    836         }
     829  atom *ptr = start;
     830
     831  while (ptr->next != end) {
     832    ptr = ptr->next;
     833    for (int j=0;j<MDSteps;j++)
     834      Trajectories[ptr].R.at(j).Translate(trans);
     835    ptr->x.Translate(trans);
     836  }
    837837};
    838838
     
    842842void molecule::Mirror(const Vector *n)
    843843{
    844         atom *ptr = start;
    845 
    846         while (ptr->next != end) {
    847                 ptr = ptr->next;
    848                 for (int j=0;j<MDSteps;j++)
    849                         Trajectories[ptr].R.at(j).Mirror(n);
    850                 ptr->x.Mirror(n);
    851         }
     844  atom *ptr = start;
     845
     846  while (ptr->next != end) {
     847    ptr = ptr->next;
     848    for (int j=0;j<MDSteps;j++)
     849      Trajectories[ptr].R.at(j).Mirror(n);
     850    ptr->x.Mirror(n);
     851  }
    852852};
    853853
     
    857857void molecule::DetermineCenter(Vector &Center)
    858858{
    859         atom *Walker = start;
    860         bond *Binder = NULL;
    861         double *matrix = ReturnFullMatrixforSymmetric(cell_size);
    862         double tmp;
    863         bool flag;
    864         Vector Testvector, Translationvector;
    865 
    866         do {
    867                 Center.Zero();
    868                 flag = true;
    869                 while (Walker->next != end) {
    870                         Walker = Walker->next;
     859  atom *Walker = start;
     860  bond *Binder = NULL;
     861  double *matrix = ReturnFullMatrixforSymmetric(cell_size);
     862  double tmp;
     863  bool flag;
     864  Vector Testvector, Translationvector;
     865
     866  do {
     867    Center.Zero();
     868    flag = true;
     869    while (Walker->next != end) {
     870      Walker = Walker->next;
    871871#ifdef ADDHYDROGEN
    872                         if (Walker->type->Z != 1) {
     872      if (Walker->type->Z != 1) {
    873873#endif
    874                                 Testvector.CopyVector(&Walker->x);
    875                                 Testvector.InverseMatrixMultiplication(matrix);
    876                                 Translationvector.Zero();
    877                                 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {
    878                                         Binder = ListOfBondsPerAtom[Walker->nr][i];
    879                                         if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing
    880                                                 for (int j=0;j<NDIM;j++) {
    881                                                         tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j];
    882                                                         if ((fabs(tmp)) > BondDistance) {
    883                                                                 flag = false;
    884                                                                 cout << Verbose(0) << "Hit: atom " << Walker->Name << " in bond " << *Binder << " has to be shifted due to " << tmp << "." << endl;
    885                                                                 if (tmp > 0)
    886                                                                         Translationvector.x[j] -= 1.;
    887                                                                 else
    888                                                                         Translationvector.x[j] += 1.;
    889                                                         }
    890                                                 }
    891                                 }
    892                                 Testvector.AddVector(&Translationvector);
    893                                 Testvector.MatrixMultiplication(matrix);
    894                                 Center.AddVector(&Testvector);
    895                                 cout << Verbose(1) << "vector is: ";
    896                                 Testvector.Output((ofstream *)&cout);
    897                                 cout << endl;
     874        Testvector.CopyVector(&Walker->x);
     875        Testvector.InverseMatrixMultiplication(matrix);
     876        Translationvector.Zero();
     877        for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {
     878          Binder = ListOfBondsPerAtom[Walker->nr][i];
     879          if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing
     880            for (int j=0;j<NDIM;j++) {
     881              tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j];
     882              if ((fabs(tmp)) > BondDistance) {
     883                flag = false;
     884                cout << Verbose(0) << "Hit: atom " << Walker->Name << " in bond " << *Binder << " has to be shifted due to " << tmp << "." << endl;
     885                if (tmp > 0)
     886                  Translationvector.x[j] -= 1.;
     887                else
     888                  Translationvector.x[j] += 1.;
     889              }
     890            }
     891        }
     892        Testvector.AddVector(&Translationvector);
     893        Testvector.MatrixMultiplication(matrix);
     894        Center.AddVector(&Testvector);
     895        cout << Verbose(1) << "vector is: ";
     896        Testvector.Output((ofstream *)&cout);
     897        cout << endl;
    898898#ifdef ADDHYDROGEN
    899                                 // now also change all hydrogens
    900                                 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {
    901                                         Binder = ListOfBondsPerAtom[Walker->nr][i];
    902                                         if (Binder->GetOtherAtom(Walker)->type->Z == 1) {
    903                                                 Testvector.CopyVector(&Binder->GetOtherAtom(Walker)->x);
    904                                                 Testvector.InverseMatrixMultiplication(matrix);
    905                                                 Testvector.AddVector(&Translationvector);
    906                                                 Testvector.MatrixMultiplication(matrix);
    907                                                 Center.AddVector(&Testvector);
    908                                                 cout << Verbose(1) << "Hydrogen vector is: ";
    909                                                 Testvector.Output((ofstream *)&cout);
    910                                                 cout << endl;
    911                                         }
    912                                 }
    913                         }
     899        // now also change all hydrogens
     900        for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {
     901          Binder = ListOfBondsPerAtom[Walker->nr][i];
     902          if (Binder->GetOtherAtom(Walker)->type->Z == 1) {
     903            Testvector.CopyVector(&Binder->GetOtherAtom(Walker)->x);
     904            Testvector.InverseMatrixMultiplication(matrix);
     905            Testvector.AddVector(&Translationvector);
     906            Testvector.MatrixMultiplication(matrix);
     907            Center.AddVector(&Testvector);
     908            cout << Verbose(1) << "Hydrogen vector is: ";
     909            Testvector.Output((ofstream *)&cout);
     910            cout << endl;
     911          }
     912        }
     913      }
    914914#endif
    915                 }
    916         } while (!flag);
    917         Free((void **)&matrix, "molecule::DetermineCenter: *matrix");
    918         Center.Scale(1./(double)AtomCount);
     915    }
     916  } while (!flag);
     917  Free((void **)&matrix, "molecule::DetermineCenter: *matrix");
     918  Center.Scale(1./(double)AtomCount);
    919919};
    920920
     
    925925void molecule::PrincipalAxisSystem(ofstream *out, bool DoRotate)
    926926{
    927         atom *ptr = start;      // start at first in list
    928         double InertiaTensor[NDIM*NDIM];
    929         Vector *CenterOfGravity = DetermineCenterOfGravity(out);
    930 
    931         CenterGravity(out, CenterOfGravity);
    932 
    933         // reset inertia tensor
    934         for(int i=0;i<NDIM*NDIM;i++)
    935                 InertiaTensor[i] = 0.;
    936 
    937         // sum up inertia tensor
    938         while (ptr->next != end) {
    939                 ptr = ptr->next;
    940                 Vector x;
    941                 x.CopyVector(&ptr->x);
    942                 //x.SubtractVector(CenterOfGravity);
    943                 InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]);
    944                 InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]);
    945                 InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]);
    946                 InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]);
    947                 InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]);
    948                 InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]);
    949                 InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]);
    950                 InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]);
    951                 InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]);
    952         }
    953         // print InertiaTensor for debugging
    954         *out << "The inertia tensor is:" << endl;
    955         for(int i=0;i<NDIM;i++) {
    956                 for(int j=0;j<NDIM;j++)
    957                         *out << InertiaTensor[i*NDIM+j] << " ";
    958                 *out << endl;
    959         }
    960         *out << endl;
    961 
    962         // diagonalize to determine principal axis system
    963         gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(NDIM);
    964         gsl_matrix_view m = gsl_matrix_view_array(InertiaTensor, NDIM, NDIM);
    965         gsl_vector *eval = gsl_vector_alloc(NDIM);
    966         gsl_matrix *evec = gsl_matrix_alloc(NDIM, NDIM);
    967         gsl_eigen_symmv(&m.matrix, eval, evec, T);
    968         gsl_eigen_symmv_free(T);
    969         gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC);
    970 
    971         for(int i=0;i<NDIM;i++) {
    972                 *out << Verbose(1) << "eigenvalue = " << gsl_vector_get(eval, i);
    973                 *out << ", eigenvector = (" << evec->data[i * evec->tda + 0] << "," << evec->data[i * evec->tda + 1] << "," << evec->data[i * evec->tda + 2] << ")" << endl;
    974         }
    975 
    976         // check whether we rotate or not
    977         if (DoRotate) {
    978                 *out << Verbose(1) << "Transforming molecule into PAS ... ";
    979                 // the eigenvectors specify the transformation matrix
    980                 ptr = start;
    981                 while (ptr->next != end) {
    982                         ptr = ptr->next;
    983                         for (int j=0;j<MDSteps;j++)
    984                                 Trajectories[ptr].R.at(j).MatrixMultiplication(evec->data);
    985                         ptr->x.MatrixMultiplication(evec->data);
    986                 }
    987                 *out << "done." << endl;
    988 
    989                 // summing anew for debugging (resulting matrix has to be diagonal!)
    990                 // reset inertia tensor
    991                 for(int i=0;i<NDIM*NDIM;i++)
    992                         InertiaTensor[i] = 0.;
    993 
    994                 // sum up inertia tensor
    995                 ptr = start;
    996                 while (ptr->next != end) {
    997                         ptr = ptr->next;
    998                         Vector x;
    999                         x.CopyVector(&ptr->x);
    1000                         //x.SubtractVector(CenterOfGravity);
    1001                         InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]);
    1002                         InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]);
    1003                         InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]);
    1004                         InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]);
    1005                         InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]);
    1006                         InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]);
    1007                         InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]);
    1008                         InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]);
    1009                         InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]);
    1010                 }
    1011                 // print InertiaTensor for debugging
    1012                 *out << "The inertia tensor is:" << endl;
    1013                 for(int i=0;i<NDIM;i++) {
    1014                         for(int j=0;j<NDIM;j++)
    1015                                 *out << InertiaTensor[i*NDIM+j] << " ";
    1016                         *out << endl;
    1017                 }
    1018                 *out << endl;
    1019         }
    1020 
    1021         // free everything
    1022         delete(CenterOfGravity);
    1023         gsl_vector_free(eval);
    1024         gsl_matrix_free(evec);
     927  atom *ptr = start;  // start at first in list
     928  double InertiaTensor[NDIM*NDIM];
     929  Vector *CenterOfGravity = DetermineCenterOfGravity(out);
     930
     931  CenterGravity(out, CenterOfGravity);
     932
     933  // reset inertia tensor
     934  for(int i=0;i<NDIM*NDIM;i++)
     935    InertiaTensor[i] = 0.;
     936
     937  // sum up inertia tensor
     938  while (ptr->next != end) {
     939    ptr = ptr->next;
     940    Vector x;
     941    x.CopyVector(&ptr->x);
     942    //x.SubtractVector(CenterOfGravity);
     943    InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]);
     944    InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]);
     945    InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]);
     946    InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]);
     947    InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]);
     948    InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]);
     949    InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]);
     950    InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]);
     951    InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]);
     952  }
     953  // print InertiaTensor for debugging
     954  *out << "The inertia tensor is:" << endl;
     955  for(int i=0;i<NDIM;i++) {
     956    for(int j=0;j<NDIM;j++)
     957      *out << InertiaTensor[i*NDIM+j] << " ";
     958    *out << endl;
     959  }
     960  *out << endl;
     961
     962  // diagonalize to determine principal axis system
     963  gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(NDIM);
     964  gsl_matrix_view m = gsl_matrix_view_array(InertiaTensor, NDIM, NDIM);
     965  gsl_vector *eval = gsl_vector_alloc(NDIM);
     966  gsl_matrix *evec = gsl_matrix_alloc(NDIM, NDIM);
     967  gsl_eigen_symmv(&m.matrix, eval, evec, T);
     968  gsl_eigen_symmv_free(T);
     969  gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC);
     970
     971  for(int i=0;i<NDIM;i++) {
     972    *out << Verbose(1) << "eigenvalue = " << gsl_vector_get(eval, i);
     973    *out << ", eigenvector = (" << evec->data[i * evec->tda + 0] << "," << evec->data[i * evec->tda + 1] << "," << evec->data[i * evec->tda + 2] << ")" << endl;
     974  }
     975
     976  // check whether we rotate or not
     977  if (DoRotate) {
     978    *out << Verbose(1) << "Transforming molecule into PAS ... ";
     979    // the eigenvectors specify the transformation matrix
     980    ptr = start;
     981    while (ptr->next != end) {
     982      ptr = ptr->next;
     983      for (int j=0;j<MDSteps;j++)
     984        Trajectories[ptr].R.at(j).MatrixMultiplication(evec->data);
     985      ptr->x.MatrixMultiplication(evec->data);
     986    }
     987    *out << "done." << endl;
     988
     989    // summing anew for debugging (resulting matrix has to be diagonal!)
     990    // reset inertia tensor
     991    for(int i=0;i<NDIM*NDIM;i++)
     992      InertiaTensor[i] = 0.;
     993
     994    // sum up inertia tensor
     995    ptr = start;
     996    while (ptr->next != end) {
     997      ptr = ptr->next;
     998      Vector x;
     999      x.CopyVector(&ptr->x);
     1000      //x.SubtractVector(CenterOfGravity);
     1001      InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]);
     1002      InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]);
     1003      InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]);
     1004      InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]);
     1005      InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]);
     1006      InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]);
     1007      InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]);
     1008      InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]);
     1009      InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]);
     1010    }
     1011    // print InertiaTensor for debugging
     1012    *out << "The inertia tensor is:" << endl;
     1013    for(int i=0;i<NDIM;i++) {
     1014      for(int j=0;j<NDIM;j++)
     1015        *out << InertiaTensor[i*NDIM+j] << " ";
     1016      *out << endl;
     1017    }
     1018    *out << endl;
     1019  }
     1020
     1021  // free everything
     1022  delete(CenterOfGravity);
     1023  gsl_vector_free(eval);
     1024  gsl_matrix_free(evec);
    10251025};
    10261026
     
    10361036bool molecule::VerletForceIntegration(char *file, double delta_t, bool IsAngstroem)
    10371037{
    1038         element *runner = elemente->start;
    1039         atom *walker = NULL;
    1040         int AtomNo;
    1041         ifstream input(file);
    1042         string token;
    1043         stringstream item;
    1044         double a, IonMass;
    1045         ForceMatrix Force;
    1046         Vector tmpvector;
    1047 
    1048         CountElements();        // make sure ElementsInMolecule is up to date
    1049 
    1050         // check file
    1051         if (input == NULL) {
    1052                 return false;
    1053         } else {
    1054                 // parse file into ForceMatrix
    1055                 if (!Force.ParseMatrix(file, 0,0,0)) {
    1056                         cerr << "Could not parse Force Matrix file " << file << "." << endl;
    1057                         return false;
    1058                 }
    1059                 if (Force.RowCounter[0] != AtomCount) {
    1060                         cerr << "Mismatch between number of atoms in file " << Force.RowCounter[0] << " and in molecule " << AtomCount << "." << endl;
    1061                         return false;
    1062                 }
    1063                 // correct Forces
    1064 //              for(int d=0;d<NDIM;d++)
    1065 //                      tmpvector.x[d] = 0.;
    1066 //              for(int i=0;i<AtomCount;i++)
    1067 //                      for(int d=0;d<NDIM;d++) {
    1068 //                              tmpvector.x[d] += Force.Matrix[0][i][d+5];
    1069 //                      }
    1070 //              for(int i=0;i<AtomCount;i++)
    1071 //                      for(int d=0;d<NDIM;d++) {
    1072 //                              Force.Matrix[0][i][d+5] -= tmpvector.x[d]/(double)AtomCount;
    1073 //                      }
    1074                 // and perform Verlet integration for each atom with position, velocity and force vector
    1075                 runner = elemente->start;
    1076                 while (runner->next != elemente->end) { // go through every element
    1077                         runner = runner->next;
    1078                         IonMass = runner->mass;
    1079                         a = delta_t*0.5/IonMass;                                // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a
    1080                         if (ElementsInMolecule[runner->Z]) { // if this element got atoms
    1081                                 AtomNo = 0;
    1082                                 walker = start;
    1083                                 while (walker->next != end) { // go through every atom of this element
    1084                                         walker = walker->next;
    1085                                         if (walker->type == runner) { // if this atom fits to element
    1086                                                 // check size of vectors
    1087                                                 if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) {
    1088                                                         //cout << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl;
    1089                                                         Trajectories[walker].R.resize(MDSteps+10);
    1090                                                         Trajectories[walker].U.resize(MDSteps+10);
    1091                                                         Trajectories[walker].F.resize(MDSteps+10);
    1092                                                 }
    1093                                                 // 1. calculate x(t+\delta t)
    1094                                                 for (int d=0; d<NDIM; d++) {
    1095                                                         Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5];
    1096                                                         Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d];
    1097                                                         Trajectories[walker].R.at(MDSteps).x[d] += delta_t*(Trajectories[walker].U.at(MDSteps-1).x[d]);
    1098                                                         Trajectories[walker].R.at(MDSteps).x[d] += 0.5*delta_t*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d])/IonMass;             // F = m * a and s = 0.5 * F/m * t^2 = F * a * t
    1099                                                 }
    1100                                                 // 2. Calculate v(t+\delta t)
    1101                                                 for (int d=0; d<NDIM; d++) {
    1102                                                         Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d];
    1103                                                         Trajectories[walker].U.at(MDSteps).x[d] += 0.5*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d]+Trajectories[walker].F.at(MDSteps).x[d])/IonMass;
    1104                                                 }
    1105 //                                              cout << "Integrated position&velocity of step " << (MDSteps) << ": (";
    1106 //                                              for (int d=0;d<NDIM;d++)
    1107 //                                                      cout << Trajectories[walker].R.at(MDSteps).x[d] << " ";                                 // next step
    1108 //                                              cout << ")\t(";
    1109 //                                              for (int d=0;d<NDIM;d++)
    1110 //                                                      cout << Trajectories[walker].U.at(MDSteps).x[d] << " ";                                 // next step
    1111 //                                              cout << ")" << endl;
    1112                                                 // next atom
    1113                                                 AtomNo++;
    1114                                         }
    1115                                 }
    1116                         }
    1117                 }
    1118         }
    1119 //      // correct velocities (rather momenta) so that center of mass remains motionless
    1120 //      tmpvector.zero()
    1121 //      IonMass = 0.;
    1122 //      walker = start;
    1123 //      while (walker->next != end) { // go through every atom
    1124 //              walker = walker->next;
    1125 //              IonMass += walker->type->mass;  // sum up total mass
    1126 //              for(int d=0;d<NDIM;d++) {
    1127 //                      tmpvector.x[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass;
    1128 //              }
    1129 //      }
    1130 //      walker = start;
    1131 //      while (walker->next != end) { // go through every atom of this element
    1132 //              walker = walker->next;
    1133 //              for(int d=0;d<NDIM;d++) {
    1134 //                      Trajectories[walker].U.at(MDSteps).x[d] -= tmpvector.x[d]*walker->type->mass/IonMass;
    1135 //              }
    1136 //      }
    1137         MDSteps++;
    1138 
    1139 
    1140         // exit
    1141         return true;
     1038  element *runner = elemente->start;
     1039  atom *walker = NULL;
     1040  int AtomNo;
     1041  ifstream input(file);
     1042  string token;
     1043  stringstream item;
     1044  double a, IonMass;
     1045  ForceMatrix Force;
     1046  Vector tmpvector;
     1047
     1048  CountElements();  // make sure ElementsInMolecule is up to date
     1049
     1050  // check file
     1051  if (input == NULL) {
     1052    return false;
     1053  } else {
     1054    // parse file into ForceMatrix
     1055    if (!Force.ParseMatrix(file, 0,0,0)) {
     1056      cerr << "Could not parse Force Matrix file " << file << "." << endl;
     1057      return false;
     1058    }
     1059    if (Force.RowCounter[0] != AtomCount) {
     1060      cerr << "Mismatch between number of atoms in file " << Force.RowCounter[0] << " and in molecule " << AtomCount << "." << endl;
     1061      return false;
     1062    }
     1063    // correct Forces
     1064//    for(int d=0;d<NDIM;d++)
     1065//      tmpvector.x[d] = 0.;
     1066//    for(int i=0;i<AtomCount;i++)
     1067//      for(int d=0;d<NDIM;d++) {
     1068//        tmpvector.x[d] += Force.Matrix[0][i][d+5];
     1069//      }
     1070//    for(int i=0;i<AtomCount;i++)
     1071//      for(int d=0;d<NDIM;d++) {
     1072//        Force.Matrix[0][i][d+5] -= tmpvector.x[d]/(double)AtomCount;
     1073//      }
     1074    // and perform Verlet integration for each atom with position, velocity and force vector
     1075    runner = elemente->start;
     1076    while (runner->next != elemente->end) { // go through every element
     1077      runner = runner->next;
     1078      IonMass = runner->mass;
     1079      a = delta_t*0.5/IonMass;        // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a
     1080      if (ElementsInMolecule[runner->Z]) { // if this element got atoms
     1081        AtomNo = 0;
     1082        walker = start;
     1083        while (walker->next != end) { // go through every atom of this element
     1084          walker = walker->next;
     1085          if (walker->type == runner) { // if this atom fits to element
     1086            // check size of vectors
     1087            if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) {
     1088              //cout << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl;
     1089              Trajectories[walker].R.resize(MDSteps+10);
     1090              Trajectories[walker].U.resize(MDSteps+10);
     1091              Trajectories[walker].F.resize(MDSteps+10);
     1092            }
     1093            // 1. calculate x(t+\delta t)
     1094            for (int d=0; d<NDIM; d++) {
     1095              Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5];
     1096              Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d];
     1097              Trajectories[walker].R.at(MDSteps).x[d] += delta_t*(Trajectories[walker].U.at(MDSteps-1).x[d]);
     1098              Trajectories[walker].R.at(MDSteps).x[d] += 0.5*delta_t*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d])/IonMass;    // F = m * a and s = 0.5 * F/m * t^2 = F * a * t
     1099            }
     1100            // 2. Calculate v(t+\delta t)
     1101            for (int d=0; d<NDIM; d++) {
     1102              Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d];
     1103              Trajectories[walker].U.at(MDSteps).x[d] += 0.5*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d]+Trajectories[walker].F.at(MDSteps).x[d])/IonMass;
     1104            }
     1105//            cout << "Integrated position&velocity of step " << (MDSteps) << ": (";
     1106//            for (int d=0;d<NDIM;d++)
     1107//              cout << Trajectories[walker].R.at(MDSteps).x[d] << " ";          // next step
     1108//            cout << ")\t(";
     1109//            for (int d=0;d<NDIM;d++)
     1110//              cout << Trajectories[walker].U.at(MDSteps).x[d] << " ";          // next step
     1111//            cout << ")" << endl;
     1112            // next atom
     1113            AtomNo++;
     1114          }
     1115        }
     1116      }
     1117    }
     1118  }
     1119//  // correct velocities (rather momenta) so that center of mass remains motionless
     1120//  tmpvector.zero()
     1121//  IonMass = 0.;
     1122//  walker = start;
     1123//  while (walker->next != end) { // go through every atom
     1124//    walker = walker->next;
     1125//    IonMass += walker->type->mass;  // sum up total mass
     1126//    for(int d=0;d<NDIM;d++) {
     1127//      tmpvector.x[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass;
     1128//    }
     1129//  }
     1130//  walker = start;
     1131//  while (walker->next != end) { // go through every atom of this element
     1132//    walker = walker->next;
     1133//    for(int d=0;d<NDIM;d++) {
     1134//      Trajectories[walker].U.at(MDSteps).x[d] -= tmpvector.x[d]*walker->type->mass/IonMass;
     1135//    }
     1136//  }
     1137  MDSteps++;
     1138
     1139
     1140  // exit
     1141  return true;
    11421142};
    11431143
     
    11471147void molecule::Align(Vector *n)
    11481148{
    1149         atom *ptr = start;
    1150         double alpha, tmp;
    1151         Vector z_axis;
    1152         z_axis.x[0] = 0.;
    1153         z_axis.x[1] = 0.;
    1154         z_axis.x[2] = 1.;
    1155 
    1156         // rotate on z-x plane
    1157         cout << Verbose(0) << "Begin of Aligning all atoms." << endl;
    1158         alpha = atan(-n->x[0]/n->x[2]);
    1159         cout << Verbose(1) << "Z-X-angle: " << alpha << " ... ";
    1160         while (ptr->next != end) {
    1161                 ptr = ptr->next;
    1162                 tmp = ptr->x.x[0];
    1163                 ptr->x.x[0] =   cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];
    1164                 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];
    1165                 for (int j=0;j<MDSteps;j++) {
    1166                         tmp = Trajectories[ptr].R.at(j).x[0];
    1167                         Trajectories[ptr].R.at(j).x[0] =        cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];
    1168                         Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2];
    1169                 }
    1170         }
    1171         // rotate n vector
    1172         tmp = n->x[0];
    1173         n->x[0] =       cos(alpha) * tmp +      sin(alpha) * n->x[2];
    1174         n->x[2] = -sin(alpha) * tmp +   cos(alpha) * n->x[2];
    1175         cout << Verbose(1) << "alignment vector after first rotation: ";
    1176         n->Output((ofstream *)&cout);
    1177         cout << endl;
    1178 
    1179         // rotate on z-y plane
    1180         ptr = start;
    1181         alpha = atan(-n->x[1]/n->x[2]);
    1182         cout << Verbose(1) << "Z-Y-angle: " << alpha << " ... ";
    1183         while (ptr->next != end) {
    1184                 ptr = ptr->next;
    1185                 tmp = ptr->x.x[1];
    1186                 ptr->x.x[1] =   cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];
    1187                 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];
    1188                 for (int j=0;j<MDSteps;j++) {
    1189                         tmp = Trajectories[ptr].R.at(j).x[1];
    1190                         Trajectories[ptr].R.at(j).x[1] =        cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];
    1191                         Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2];
    1192                 }
    1193         }
    1194         // rotate n vector (for consistency check)
    1195         tmp = n->x[1];
    1196         n->x[1] =       cos(alpha) * tmp +      sin(alpha) * n->x[2];
    1197         n->x[2] = -sin(alpha) * tmp +   cos(alpha) * n->x[2];
    1198 
    1199         cout << Verbose(1) << "alignment vector after second rotation: ";
    1200         n->Output((ofstream *)&cout);
    1201         cout << Verbose(1) << endl;
    1202         cout << Verbose(0) << "End of Aligning all atoms." << endl;
     1149  atom *ptr = start;
     1150  double alpha, tmp;
     1151  Vector z_axis;
     1152  z_axis.x[0] = 0.;
     1153  z_axis.x[1] = 0.;
     1154  z_axis.x[2] = 1.;
     1155
     1156  // rotate on z-x plane
     1157  cout << Verbose(0) << "Begin of Aligning all atoms." << endl;
     1158  alpha = atan(-n->x[0]/n->x[2]);
     1159  cout << Verbose(1) << "Z-X-angle: " << alpha << " ... ";
     1160  while (ptr->next != end) {
     1161    ptr = ptr->next;
     1162    tmp = ptr->x.x[0];
     1163    ptr->x.x[0] =  cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];
     1164    ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];
     1165    for (int j=0;j<MDSteps;j++) {
     1166      tmp = Trajectories[ptr].R.at(j).x[0];
     1167      Trajectories[ptr].R.at(j).x[0] =  cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];
     1168      Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2];
     1169    }
     1170  }
     1171  // rotate n vector
     1172  tmp = n->x[0];
     1173  n->x[0] =  cos(alpha) * tmp +  sin(alpha) * n->x[2];
     1174  n->x[2] = -sin(alpha) * tmp +  cos(alpha) * n->x[2];
     1175  cout << Verbose(1) << "alignment vector after first rotation: ";
     1176  n->Output((ofstream *)&cout);
     1177  cout << endl;
     1178
     1179  // rotate on z-y plane
     1180  ptr = start;
     1181  alpha = atan(-n->x[1]/n->x[2]);
     1182  cout << Verbose(1) << "Z-Y-angle: " << alpha << " ... ";
     1183  while (ptr->next != end) {
     1184    ptr = ptr->next;
     1185    tmp = ptr->x.x[1];
     1186    ptr->x.x[1] =  cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];
     1187    ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];
     1188    for (int j=0;j<MDSteps;j++) {
     1189      tmp = Trajectories[ptr].R.at(j).x[1];
     1190      Trajectories[ptr].R.at(j).x[1] =  cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];
     1191      Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2];
     1192    }
     1193  }
     1194  // rotate n vector (for consistency check)
     1195  tmp = n->x[1];
     1196  n->x[1] =  cos(alpha) * tmp +  sin(alpha) * n->x[2];
     1197  n->x[2] = -sin(alpha) * tmp +  cos(alpha) * n->x[2];
     1198
     1199  cout << Verbose(1) << "alignment vector after second rotation: ";
     1200  n->Output((ofstream *)&cout);
     1201  cout << Verbose(1) << endl;
     1202  cout << Verbose(0) << "End of Aligning all atoms." << endl;
    12031203};
    12041204
     
    12091209bool molecule::RemoveAtom(atom *pointer)
    12101210{
    1211         if (ElementsInMolecule[pointer->type->Z] != 0)  { // this would indicate an error
    1212                 ElementsInMolecule[pointer->type->Z]--; // decrease number of atom of this element
    1213           AtomCount--;
    1214         } else
    1215                 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl;
    1216         if (ElementsInMolecule[pointer->type->Z] == 0)  // was last atom of this element?
    1217                 ElementCount--;
    1218         Trajectories.erase(pointer);
    1219         return remove(pointer, start, end);
     1211  if (ElementsInMolecule[pointer->type->Z] != 0)  { // this would indicate an error
     1212    ElementsInMolecule[pointer->type->Z]--;  // decrease number of atom of this element
     1213    AtomCount--;
     1214  } else
     1215    cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl;
     1216  if (ElementsInMolecule[pointer->type->Z] == 0)  // was last atom of this element?
     1217    ElementCount--;
     1218  Trajectories.erase(pointer);
     1219  return remove(pointer, start, end);
    12201220};
    12211221
     
    12441244bool molecule::CleanupMolecule()
    12451245{
    1246         return (cleanup(start,end) && cleanup(first,last));
     1246  return (cleanup(start,end) && cleanup(first,last));
    12471247};
    12481248
     
    12511251 * \return pointer to atom or NULL
    12521252 */
    1253 atom * molecule::FindAtom(int Nr)       const{
    1254         atom * walker = find(&Nr, start,end);
    1255         if (walker != NULL) {
    1256                 //cout << Verbose(0) << "Found Atom Nr. " << walker->nr << endl;
    1257                 return walker;
    1258         } else {
    1259                 cout << Verbose(0) << "Atom not found in list." << endl;
    1260                 return NULL;
    1261         }
     1253atom * molecule::FindAtom(int Nr)  const{
     1254  atom * walker = find(&Nr, start,end);
     1255  if (walker != NULL) {
     1256    //cout << Verbose(0) << "Found Atom Nr. " << walker->nr << endl;
     1257    return walker;
     1258  } else {
     1259    cout << Verbose(0) << "Atom not found in list." << endl;
     1260    return NULL;
     1261  }
    12621262};
    12631263
     
    12671267atom * molecule::AskAtom(string text)
    12681268{
    1269         int No;
    1270         atom *ion = NULL;
    1271         do {
    1272                 //cout << Verbose(0) << "============Atom list==========================" << endl;
    1273                 //mol->Output((ofstream *)&cout);
    1274                 //cout << Verbose(0) << "===============================================" << endl;
    1275                 cout << Verbose(0) << text;
    1276                 cin >> No;
    1277                 ion = this->FindAtom(No);
    1278         } while (ion == NULL);
    1279         return ion;
     1269  int No;
     1270  atom *ion = NULL;
     1271  do {
     1272    //cout << Verbose(0) << "============Atom list==========================" << endl;
     1273    //mol->Output((ofstream *)&cout);
     1274    //cout << Verbose(0) << "===============================================" << endl;
     1275    cout << Verbose(0) << text;
     1276    cin >> No;
     1277    ion = this->FindAtom(No);
     1278  } while (ion == NULL);
     1279  return ion;
    12801280};
    12811281
     
    12861286bool molecule::CheckBounds(const Vector *x) const
    12871287{
    1288         bool result = true;
    1289         int j =-1;
    1290         for (int i=0;i<NDIM;i++) {
    1291                 j += i+1;
    1292                 result = result && ((x->x[i] >= 0) && (x->x[i] < cell_size[j]));
    1293         }
    1294         //return result;
    1295         return true; /// probably not gonna use the check no more
     1288  bool result = true;
     1289  int j =-1;
     1290  for (int i=0;i<NDIM;i++) {
     1291    j += i+1;
     1292    result = result && ((x->x[i] >= 0) && (x->x[i] < cell_size[j]));
     1293  }
     1294  //return result;
     1295  return true; /// probably not gonna use the check no more
    12961296};
    12971297
     
    13031303double LeastSquareDistance (const gsl_vector * x, void * params)
    13041304{
    1305         double res = 0, t;
    1306         Vector a,b,c,d;
    1307         struct lsq_params *par = (struct lsq_params *)params;
    1308         atom *ptr = par->mol->start;
    1309 
    1310         // initialize vectors
    1311         a.x[0] = gsl_vector_get(x,0);
    1312         a.x[1] = gsl_vector_get(x,1);
    1313         a.x[2] = gsl_vector_get(x,2);
    1314         b.x[0] = gsl_vector_get(x,3);
    1315         b.x[1] = gsl_vector_get(x,4);
    1316         b.x[2] = gsl_vector_get(x,5);
    1317         // go through all atoms
    1318         while (ptr != par->mol->end) {
    1319                 ptr = ptr->next;
    1320                 if (ptr->type == ((struct lsq_params *)params)->type) { // for specific type
    1321                         c.CopyVector(&ptr->x);  // copy vector to temporary one
    1322                         c.SubtractVector(&a);    // subtract offset vector
    1323                         t = c.ScalarProduct(&b);                                        // get direction parameter
    1324                         d.CopyVector(&b);                        // and create vector
    1325                         d.Scale(&t);
    1326                         c.SubtractVector(&d);    // ... yielding distance vector
    1327                         res += d.ScalarProduct((const Vector *)&d);                             // add squared distance
    1328                 }
    1329         }
    1330         return res;
     1305  double res = 0, t;
     1306  Vector a,b,c,d;
     1307  struct lsq_params *par = (struct lsq_params *)params;
     1308  atom *ptr = par->mol->start;
     1309
     1310  // initialize vectors
     1311  a.x[0] = gsl_vector_get(x,0);
     1312  a.x[1] = gsl_vector_get(x,1);
     1313  a.x[2] = gsl_vector_get(x,2);
     1314  b.x[0] = gsl_vector_get(x,3);
     1315  b.x[1] = gsl_vector_get(x,4);
     1316  b.x[2] = gsl_vector_get(x,5);
     1317  // go through all atoms
     1318  while (ptr != par->mol->end) {
     1319    ptr = ptr->next;
     1320    if (ptr->type == ((struct lsq_params *)params)->type) { // for specific type
     1321      c.CopyVector(&ptr->x);  // copy vector to temporary one
     1322      c.SubtractVector(&a);  // subtract offset vector
     1323      t = c.ScalarProduct(&b);          // get direction parameter
     1324      d.CopyVector(&b);      // and create vector
     1325      d.Scale(&t);
     1326      c.SubtractVector(&d);  // ... yielding distance vector
     1327      res += d.ScalarProduct((const Vector *)&d);        // add squared distance
     1328    }
     1329  }
     1330  return res;
    13311331};
    13321332
     
    13361336void molecule::GetAlignvector(struct lsq_params * par) const
    13371337{
    1338                 int np = 6;
    1339 
    1340         const gsl_multimin_fminimizer_type *T =
    1341                 gsl_multimin_fminimizer_nmsimplex;
    1342         gsl_multimin_fminimizer *s = NULL;
    1343         gsl_vector *ss;
    1344         gsl_multimin_function minex_func;
    1345 
    1346         size_t iter = 0, i;
    1347         int status;
    1348         double size;
    1349 
    1350         /* Initial vertex size vector */
    1351         ss = gsl_vector_alloc (np);
    1352 
    1353         /* Set all step sizes to 1 */
    1354         gsl_vector_set_all (ss, 1.0);
    1355 
    1356         /* Starting point */
    1357         par->x = gsl_vector_alloc (np);
    1358         par->mol = this;
    1359 
    1360          gsl_vector_set (par->x, 0, 0.0);       // offset
    1361         gsl_vector_set (par->x, 1, 0.0);
    1362         gsl_vector_set (par->x, 2, 0.0);
    1363          gsl_vector_set (par->x, 3, 0.0);       // direction
    1364         gsl_vector_set (par->x, 4, 0.0);
    1365         gsl_vector_set (par->x, 5, 1.0);
    1366 
    1367         /* Initialize method and iterate */
    1368         minex_func.f = &LeastSquareDistance;
    1369         minex_func.n = np;
    1370         minex_func.params = (void *)par;
    1371 
    1372         s = gsl_multimin_fminimizer_alloc (T, np);
    1373         gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss);
    1374 
    1375         do
    1376                 {
    1377                         iter++;
    1378                         status = gsl_multimin_fminimizer_iterate(s);
    1379 
    1380                         if (status)
    1381                                 break;
    1382 
    1383                         size = gsl_multimin_fminimizer_size (s);
    1384                         status = gsl_multimin_test_size (size, 1e-2);
    1385 
    1386                         if (status == GSL_SUCCESS)
    1387                                 {
    1388                                         printf ("converged to minimum at\n");
    1389                                 }
    1390 
    1391                         printf ("%5d ", (int)iter);
    1392                         for (i = 0; i < (size_t)np; i++)
    1393                                 {
    1394                                         printf ("%10.3e ", gsl_vector_get (s->x, i));
    1395                                 }
    1396                         printf ("f() = %7.3f size = %.3f\n", s->fval, size);
    1397                 }
    1398         while (status == GSL_CONTINUE && iter < 100);
    1399 
    1400         for (i=0;i<(size_t)np;i++)
    1401                 gsl_vector_set(par->x, i, gsl_vector_get(s->x, i));
    1402         //gsl_vector_free(par->x);
    1403         gsl_vector_free(ss);
    1404         gsl_multimin_fminimizer_free (s);
     1338    int np = 6;
     1339
     1340  const gsl_multimin_fminimizer_type *T =
     1341    gsl_multimin_fminimizer_nmsimplex;
     1342  gsl_multimin_fminimizer *s = NULL;
     1343  gsl_vector *ss;
     1344  gsl_multimin_function minex_func;
     1345
     1346  size_t iter = 0, i;
     1347  int status;
     1348  double size;
     1349
     1350  /* Initial vertex size vector */
     1351  ss = gsl_vector_alloc (np);
     1352
     1353  /* Set all step sizes to 1 */
     1354  gsl_vector_set_all (ss, 1.0);
     1355
     1356  /* Starting point */
     1357  par->x = gsl_vector_alloc (np);
     1358  par->mol = this;
     1359
     1360   gsl_vector_set (par->x, 0, 0.0);  // offset
     1361  gsl_vector_set (par->x, 1, 0.0);
     1362  gsl_vector_set (par->x, 2, 0.0);
     1363   gsl_vector_set (par->x, 3, 0.0);  // direction
     1364  gsl_vector_set (par->x, 4, 0.0);
     1365  gsl_vector_set (par->x, 5, 1.0);
     1366
     1367  /* Initialize method and iterate */
     1368  minex_func.f = &LeastSquareDistance;
     1369  minex_func.n = np;
     1370  minex_func.params = (void *)par;
     1371
     1372  s = gsl_multimin_fminimizer_alloc (T, np);
     1373  gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss);
     1374
     1375  do
     1376    {
     1377      iter++;
     1378      status = gsl_multimin_fminimizer_iterate(s);
     1379
     1380      if (status)
     1381        break;
     1382
     1383      size = gsl_multimin_fminimizer_size (s);
     1384      status = gsl_multimin_test_size (size, 1e-2);
     1385
     1386      if (status == GSL_SUCCESS)
     1387        {
     1388          printf ("converged to minimum at\n");
     1389        }
     1390
     1391      printf ("%5d ", (int)iter);
     1392      for (i = 0; i < (size_t)np; i++)
     1393        {
     1394          printf ("%10.3e ", gsl_vector_get (s->x, i));
     1395        }
     1396      printf ("f() = %7.3f size = %.3f\n", s->fval, size);
     1397    }
     1398  while (status == GSL_CONTINUE && iter < 100);
     1399
     1400  for (i=0;i<(size_t)np;i++)
     1401    gsl_vector_set(par->x, i, gsl_vector_get(s->x, i));
     1402  //gsl_vector_free(par->x);
     1403  gsl_vector_free(ss);
     1404  gsl_multimin_fminimizer_free (s);
    14051405};
    14061406
     
    14101410bool molecule::Output(ofstream *out)
    14111411{
    1412         element *runner;
    1413         atom *walker = NULL;
    1414         int ElementNo, AtomNo;
    1415         CountElements();
    1416 
    1417         if (out == NULL) {
    1418                 return false;
    1419         } else {
    1420                 *out << "#Ion_TypeNr._Nr.R[0]           R[1]            R[2]            MoveType (0 MoveIon, 1 FixedIon)" << endl;
    1421                 ElementNo = 0;
    1422                 runner = elemente->start;
    1423                 while (runner->next != elemente->end) { // go through every element
    1424                         runner = runner->next;
    1425                         if (ElementsInMolecule[runner->Z]) { // if this element got atoms
    1426                                 ElementNo++;
    1427                                 AtomNo = 0;
    1428                                 walker = start;
    1429                                 while (walker->next != end) { // go through every atom of this element
    1430                                         walker = walker->next;
    1431                                         if (walker->type == runner) { // if this atom fits to element
    1432                                                 AtomNo++;
    1433                                                 walker->Output(ElementNo, AtomNo, out); // removed due to trajectories
    1434                                         }
    1435                                 }
    1436                         }
    1437                 }
    1438                 return true;
    1439         }
     1412  element *runner;
     1413  atom *walker = NULL;
     1414  int ElementNo, AtomNo;
     1415  CountElements();
     1416
     1417  if (out == NULL) {
     1418    return false;
     1419  } else {
     1420    *out << "#Ion_TypeNr._Nr.R[0]    R[1]    R[2]    MoveType (0 MoveIon, 1 FixedIon)" << endl;
     1421    ElementNo = 0;
     1422    runner = elemente->start;
     1423    while (runner->next != elemente->end) { // go through every element
     1424      runner = runner->next;
     1425      if (ElementsInMolecule[runner->Z]) { // if this element got atoms
     1426        ElementNo++;
     1427        AtomNo = 0;
     1428        walker = start;
     1429        while (walker->next != end) { // go through every atom of this element
     1430          walker = walker->next;
     1431          if (walker->type == runner) { // if this atom fits to element
     1432            AtomNo++;
     1433            walker->Output(ElementNo, AtomNo, out); // removed due to trajectories
     1434          }
     1435        }
     1436      }
     1437    }
     1438    return true;
     1439  }
    14401440};
    14411441
     
    14451445bool molecule::OutputTrajectories(ofstream *out)
    14461446{
    1447         element *runner = NULL;
    1448         atom *walker = NULL;
    1449         int ElementNo, AtomNo;
    1450         CountElements();
    1451 
    1452         if (out == NULL) {
    1453                 return false;
    1454         } else {
    1455                 for (int step = 0; step < MDSteps; step++) {
    1456                         if (step == 0) {
    1457                                 *out << "#Ion_TypeNr._Nr.R[0]           R[1]            R[2]            MoveType (0 MoveIon, 1 FixedIon)" << endl;
    1458                         } else {
    1459                                 *out << "# ====== MD step " << step << " =========" << endl;
    1460                         }
    1461                         ElementNo = 0;
    1462                         runner = elemente->start;
    1463                         while (runner->next != elemente->end) { // go through every element
    1464                                 runner = runner->next;
    1465                                 if (ElementsInMolecule[runner->Z]) { // if this element got atoms
    1466                                         ElementNo++;
    1467                                         AtomNo = 0;
    1468                                         walker = start;
    1469                                         while (walker->next != end) { // go through every atom of this element
    1470                                                 walker = walker->next;
    1471                                                 if (walker->type == runner) { // if this atom fits to element
    1472                                                         AtomNo++;
    1473                                                         *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t"        << fixed << setprecision(9) << showpoint;
    1474                                                         *out << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2];
    1475                                                         *out << "\t" << walker->FixedIon;
    1476                                                         if (Trajectories[walker].U.at(step).Norm() > MYEPSILON)
    1477                                                                 *out << "\t" << scientific << setprecision(6) << Trajectories[walker].U.at(step).x[0] << "\t" << Trajectories[walker].U.at(step).x[1] << "\t" << Trajectories[walker].U.at(step).x[2] << "\t";
    1478                                                         if (Trajectories[walker].F.at(step).Norm() > MYEPSILON)
    1479                                                                 *out << "\t" << scientific << setprecision(6) << Trajectories[walker].F.at(step).x[0] << "\t" << Trajectories[walker].F.at(step).x[1] << "\t" << Trajectories[walker].F.at(step).x[2] << "\t";
    1480                                                         *out << "\t# Number in molecule " << walker->nr << endl;
    1481                                                 }
    1482                                         }
    1483                                 }
    1484                         }
    1485                 }
    1486                 return true;
    1487         }
     1447  element *runner = NULL;
     1448  atom *walker = NULL;
     1449  int ElementNo, AtomNo;
     1450  CountElements();
     1451
     1452  if (out == NULL) {
     1453    return false;
     1454  } else {
     1455    for (int step = 0; step < MDSteps; step++) {
     1456      if (step == 0) {
     1457        *out << "#Ion_TypeNr._Nr.R[0]    R[1]    R[2]    MoveType (0 MoveIon, 1 FixedIon)" << endl;
     1458      } else {
     1459        *out << "# ====== MD step " << step << " =========" << endl;
     1460      }
     1461      ElementNo = 0;
     1462      runner = elemente->start;
     1463      while (runner->next != elemente->end) { // go through every element
     1464        runner = runner->next;
     1465        if (ElementsInMolecule[runner->Z]) { // if this element got atoms
     1466          ElementNo++;
     1467          AtomNo = 0;
     1468          walker = start;
     1469          while (walker->next != end) { // go through every atom of this element
     1470            walker = walker->next;
     1471            if (walker->type == runner) { // if this atom fits to element
     1472              AtomNo++;
     1473              *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t"  << fixed << setprecision(9) << showpoint;
     1474              *out << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2];
     1475              *out << "\t" << walker->FixedIon;
     1476              if (Trajectories[walker].U.at(step).Norm() > MYEPSILON)
     1477                *out << "\t" << scientific << setprecision(6) << Trajectories[walker].U.at(step).x[0] << "\t" << Trajectories[walker].U.at(step).x[1] << "\t" << Trajectories[walker].U.at(step).x[2] << "\t";
     1478              if (Trajectories[walker].F.at(step).Norm() > MYEPSILON)
     1479                *out << "\t" << scientific << setprecision(6) << Trajectories[walker].F.at(step).x[0] << "\t" << Trajectories[walker].F.at(step).x[1] << "\t" << Trajectories[walker].F.at(step).x[2] << "\t";
     1480              *out << "\t# Number in molecule " << walker->nr << endl;
     1481            }
     1482          }
     1483        }
     1484      }
     1485    }
     1486    return true;
     1487  }
    14881488};
    14891489
     
    14931493void molecule::OutputListOfBonds(ofstream *out) const
    14941494{
    1495         *out << Verbose(2) << endl << "From Contents of ListOfBondsPerAtom, all non-hydrogen atoms:" << endl;
    1496         atom *Walker = start;
    1497         while (Walker->next != end) {
    1498                 Walker = Walker->next;
     1495  *out << Verbose(2) << endl << "From Contents of ListOfBondsPerAtom, all non-hydrogen atoms:" << endl;
     1496  atom *Walker = start;
     1497  while (Walker->next != end) {
     1498    Walker = Walker->next;
    14991499#ifdef ADDHYDROGEN
    1500                 if (Walker->type->Z != 1) {      // regard only non-hydrogen
     1500    if (Walker->type->Z != 1) {  // regard only non-hydrogen
    15011501#endif
    1502                         *out << Verbose(2) << "Atom " << Walker->Name << " has Bonds: "<<endl;
    1503                         for(int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) {
    1504                                 *out << Verbose(3) << *(ListOfBondsPerAtom)[Walker->nr][j] << endl;
    1505                         }
     1502      *out << Verbose(2) << "Atom " << Walker->Name << " has Bonds: "<<endl;
     1503      for(int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) {
     1504        *out << Verbose(3) << *(ListOfBondsPerAtom)[Walker->nr][j] << endl;
     1505      }
    15061506#ifdef ADDHYDROGEN
    1507                 }
     1507    }
    15081508#endif
    1509         }
    1510         *out << endl;
     1509  }
     1510  *out << endl;
    15111511};
    15121512
     
    15141514 * \param *out stream pointer
    15151515 */
    1516 bool molecule::Checkout(ofstream *out)  const
    1517 {
    1518         return elemente->Checkout(out, ElementsInMolecule);
     1516bool molecule::Checkout(ofstream *out)  const
     1517{
     1518  return elemente->Checkout(out, ElementsInMolecule);
    15191519};
    15201520
     
    15241524bool molecule::OutputTrajectoriesXYZ(ofstream *out)
    15251525{
    1526         atom *walker = NULL;
    1527         int No = 0;
    1528         time_t now;
    1529 
    1530         now = time((time_t *)NULL);      // Get the system time and put it into 'now' as 'calender time'
    1531         walker = start;
    1532         while (walker->next != end) { // go through every atom and count
    1533                 walker = walker->next;
    1534                 No++;
    1535         }
    1536         if (out != NULL) {
    1537                 for (int step=0;step<MDSteps;step++) {
    1538                         *out << No << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now);
    1539                         walker = start;
    1540                         while (walker->next != end) { // go through every atom of this element
    1541                                 walker = walker->next;
    1542                                 *out << walker->type->symbol << "\t" << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2] << endl;
    1543                         }
    1544                 }
    1545                 return true;
    1546         } else
    1547                 return false;
     1526  atom *walker = NULL;
     1527  int No = 0;
     1528  time_t now;
     1529
     1530  now = time((time_t *)NULL);  // Get the system time and put it into 'now' as 'calender time'
     1531  walker = start;
     1532  while (walker->next != end) { // go through every atom and count
     1533    walker = walker->next;
     1534    No++;
     1535  }
     1536  if (out != NULL) {
     1537    for (int step=0;step<MDSteps;step++) {
     1538      *out << No << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now);
     1539      walker = start;
     1540      while (walker->next != end) { // go through every atom of this element
     1541        walker = walker->next;
     1542        *out << walker->type->symbol << "\t" << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2] << endl;
     1543      }
     1544    }
     1545    return true;
     1546  } else
     1547    return false;
    15481548};
    15491549
     
    15531553bool molecule::OutputXYZ(ofstream *out) const
    15541554{
    1555         atom *walker = NULL;
    1556         int AtomNo = 0, ElementNo;
    1557         time_t now;
    1558         element *runner = NULL;
    1559 
    1560         now = time((time_t *)NULL);      // Get the system time and put it into 'now' as 'calender time'
    1561         walker = start;
    1562         while (walker->next != end) { // go through every atom and count
    1563                 walker = walker->next;
    1564                 AtomNo++;
    1565         }
    1566         if (out != NULL) {
    1567                 *out << AtomNo << "\n\tCreated by molecuilder on " << ctime(&now);
    1568                 ElementNo = 0;
    1569                 runner = elemente->start;
    1570                 while (runner->next != elemente->end) { // go through every element
    1571                         runner = runner->next;
    1572                         if (ElementsInMolecule[runner->Z]) { // if this element got atoms
    1573                                 ElementNo++;
    1574                                 walker = start;
    1575                                 while (walker->next != end) { // go through every atom of this element
    1576                                         walker = walker->next;
    1577                                         if (walker->type == runner) { // if this atom fits to element
    1578                                                 walker->OutputXYZLine(out);
    1579                                         }
    1580                                 }
    1581                         }
    1582                 }
    1583                 return true;
    1584         } else
    1585                 return false;
     1555  atom *walker = NULL;
     1556  int AtomNo = 0, ElementNo;
     1557  time_t now;
     1558  element *runner = NULL;
     1559
     1560  now = time((time_t *)NULL);  // Get the system time and put it into 'now' as 'calender time'
     1561  walker = start;
     1562  while (walker->next != end) { // go through every atom and count
     1563    walker = walker->next;
     1564    AtomNo++;
     1565  }
     1566  if (out != NULL) {
     1567    *out << AtomNo << "\n\tCreated by molecuilder on " << ctime(&now);
     1568    ElementNo = 0;
     1569    runner = elemente->start;
     1570    while (runner->next != elemente->end) { // go through every element
     1571      runner = runner->next;
     1572      if (ElementsInMolecule[runner->Z]) { // if this element got atoms
     1573        ElementNo++;
     1574        walker = start;
     1575        while (walker->next != end) { // go through every atom of this element
     1576          walker = walker->next;
     1577          if (walker->type == runner) { // if this atom fits to element
     1578            walker->OutputXYZLine(out);
     1579          }
     1580        }
     1581      }
     1582    }
     1583    return true;
     1584  } else
     1585    return false;
    15861586};
    15871587
     
    15911591void molecule::CountAtoms(ofstream *out)
    15921592{
    1593         int i = 0;
    1594         atom *Walker = start;
    1595         while (Walker->next != end) {
    1596                 Walker = Walker->next;
    1597                 i++;
    1598         }
    1599         if ((AtomCount == 0) || (i != AtomCount)) {
    1600                 *out << Verbose(3) << "Mismatch in AtomCount " << AtomCount << " and recounted number " << i << ", renaming all." << endl;
    1601                 AtomCount = i;
    1602 
    1603                 // count NonHydrogen atoms and give each atom a unique name
    1604                 if (AtomCount != 0) {
    1605                         i=0;
    1606                         NoNonHydrogen = 0;
    1607                         Walker = start;
    1608                         while (Walker->next != end) {
    1609                                 Walker = Walker->next;
    1610                                 Walker->nr = i; // update number in molecule (for easier referencing in FragmentMolecule lateron)
    1611                                 if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it
    1612                                         NoNonHydrogen++;
    1613                                 Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name");
    1614                                 Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name");
    1615                                 sprintf(Walker->Name, "%2s%02d", Walker->type->symbol, Walker->nr+1);
    1616                                 *out << "Naming atom nr. " << Walker->nr << " " << Walker->Name << "." << endl;
    1617                                 i++;
    1618                         }
    1619                 } else
    1620                         *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl;
    1621         }
     1593  int i = 0;
     1594  atom *Walker = start;
     1595  while (Walker->next != end) {
     1596    Walker = Walker->next;
     1597    i++;
     1598  }
     1599  if ((AtomCount == 0) || (i != AtomCount)) {
     1600    *out << Verbose(3) << "Mismatch in AtomCount " << AtomCount << " and recounted number " << i << ", renaming all." << endl;
     1601    AtomCount = i;
     1602
     1603    // count NonHydrogen atoms and give each atom a unique name
     1604    if (AtomCount != 0) {
     1605      i=0;
     1606      NoNonHydrogen = 0;
     1607      Walker = start;
     1608      while (Walker->next != end) {
     1609        Walker = Walker->next;
     1610        Walker->nr = i;  // update number in molecule (for easier referencing in FragmentMolecule lateron)
     1611        if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it
     1612          NoNonHydrogen++;
     1613        Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name");
     1614        Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name");
     1615        sprintf(Walker->Name, "%2s%02d", Walker->type->symbol, Walker->nr+1);
     1616        *out << "Naming atom nr. " << Walker->nr << " " << Walker->Name << "." << endl;
     1617        i++;
     1618      }
     1619    } else
     1620      *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl;
     1621  }
    16221622};
    16231623
     
    16261626void molecule::CountElements()
    16271627{
    1628         int i = 0;
    1629         for(i=MAX_ELEMENTS;i--;)
    1630                 ElementsInMolecule[i] = 0;
    1631         ElementCount = 0;
    1632 
    1633         atom *walker = start;
    1634         while (walker->next != end) {
    1635                 walker = walker->next;
    1636                 ElementsInMolecule[walker->type->Z]++;
    1637                 i++;
    1638         }
    1639         for(i=MAX_ELEMENTS;i--;)
    1640                 ElementCount += (ElementsInMolecule[i] != 0 ? 1 : 0);
     1628  int i = 0;
     1629  for(i=MAX_ELEMENTS;i--;)
     1630    ElementsInMolecule[i] = 0;
     1631  ElementCount = 0;
     1632
     1633  atom *walker = start;
     1634  while (walker->next != end) {
     1635    walker = walker->next;
     1636    ElementsInMolecule[walker->type->Z]++;
     1637    i++;
     1638  }
     1639  for(i=MAX_ELEMENTS;i--;)
     1640    ElementCount += (ElementsInMolecule[i] != 0 ? 1 : 0);
    16411641};
    16421642
     
    16481648int molecule::CountCyclicBonds(ofstream *out)
    16491649{
    1650         int No = 0;
    1651         int *MinimumRingSize = NULL;
    1652         MoleculeLeafClass *Subgraphs = NULL;
    1653         class StackClass<bond *> *BackEdgeStack = NULL;
    1654         bond *Binder = first;
    1655         if ((Binder->next != last) && (Binder->next->Type == Undetermined)) {
    1656                 *out << Verbose(0) << "No Depth-First-Search analysis performed so far, calling ..." << endl;
    1657                 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack);
    1658                 while (Subgraphs->next != NULL) {
    1659                         Subgraphs = Subgraphs->next;
    1660                         delete(Subgraphs->previous);
    1661                 }
    1662                 delete(Subgraphs);
    1663                 delete[](MinimumRingSize);
    1664         }
    1665         while(Binder->next != last) {
    1666                 Binder = Binder->next;
    1667                 if (Binder->Cyclic)
    1668                         No++;
    1669         }
    1670         delete(BackEdgeStack);
    1671         return No;
     1650  int No = 0;
     1651  int *MinimumRingSize = NULL;
     1652  MoleculeLeafClass *Subgraphs = NULL;
     1653  class StackClass<bond *> *BackEdgeStack = NULL;
     1654  bond *Binder = first;
     1655  if ((Binder->next != last) && (Binder->next->Type == Undetermined)) {
     1656    *out << Verbose(0) << "No Depth-First-Search analysis performed so far, calling ..." << endl;
     1657    Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack);
     1658    while (Subgraphs->next != NULL) {
     1659      Subgraphs = Subgraphs->next;
     1660      delete(Subgraphs->previous);
     1661    }
     1662    delete(Subgraphs);
     1663    delete[](MinimumRingSize);
     1664  }
     1665  while(Binder->next != last) {
     1666    Binder = Binder->next;
     1667    if (Binder->Cyclic)
     1668      No++;
     1669  }
     1670  delete(BackEdgeStack);
     1671  return No;
    16721672};
    16731673/** Returns Shading as a char string.
     
    16771677string molecule::GetColor(enum Shading color)
    16781678{
    1679         switch(color) {
    1680                 case white:
    1681                         return "white";
    1682                         break;
    1683                 case lightgray:
    1684                         return "lightgray";
    1685                         break;
    1686                 case darkgray:
    1687                         return "darkgray";
    1688                         break;
    1689                 case black:
    1690                         return "black";
    1691                         break;
    1692                 default:
    1693                         return "uncolored";
    1694                         break;
    1695         };
     1679  switch(color) {
     1680    case white:
     1681      return "white";
     1682      break;
     1683    case lightgray:
     1684      return "lightgray";
     1685      break;
     1686    case darkgray:
     1687      return "darkgray";
     1688      break;
     1689    case black:
     1690      return "black";
     1691      break;
     1692    default:
     1693      return "uncolored";
     1694      break;
     1695  };
    16961696};
    16971697
     
    17021702void molecule::CalculateOrbitals(class config &configuration)
    17031703{
    1704         configuration.MaxPsiDouble = configuration.PsiMaxNoDown = configuration.PsiMaxNoUp = configuration.PsiType = 0;
    1705         for(int i=MAX_ELEMENTS;i--;) {
    1706                 if (ElementsInMolecule[i] != 0) {
    1707                         //cout << "CalculateOrbitals: " << elemente->FindElement(i)->name << " has a valence of " << (int)elemente->FindElement(i)->Valence << " and there are " << ElementsInMolecule[i] << " of it." << endl;
    1708                         configuration.MaxPsiDouble += ElementsInMolecule[i]*((int)elemente->FindElement(i)->Valence);
    1709                 }
    1710         }
    1711         configuration.PsiMaxNoDown = configuration.MaxPsiDouble/2 + (configuration.MaxPsiDouble % 2);
    1712         configuration.PsiMaxNoUp = configuration.MaxPsiDouble/2;
    1713         configuration.MaxPsiDouble /= 2;
    1714         configuration.PsiType = (configuration.PsiMaxNoDown == configuration.PsiMaxNoUp) ? 0 : 1;
    1715         if ((configuration.PsiType == 1) && (configuration.ProcPEPsi < 2)) {
    1716                 configuration.ProcPEGamma /= 2;
    1717                 configuration.ProcPEPsi *= 2;
    1718         } else {
    1719                 configuration.ProcPEGamma *= configuration.ProcPEPsi;
    1720                 configuration.ProcPEPsi = 1;
    1721         }
    1722         configuration.InitMaxMinStopStep = configuration.MaxMinStopStep = configuration.MaxPsiDouble;
     1704  configuration.MaxPsiDouble = configuration.PsiMaxNoDown = configuration.PsiMaxNoUp = configuration.PsiType = 0;
     1705  for(int i=MAX_ELEMENTS;i--;) {
     1706    if (ElementsInMolecule[i] != 0) {
     1707      //cout << "CalculateOrbitals: " << elemente->FindElement(i)->name << " has a valence of " << (int)elemente->FindElement(i)->Valence << " and there are " << ElementsInMolecule[i] << " of it." << endl;
     1708      configuration.MaxPsiDouble += ElementsInMolecule[i]*((int)elemente->FindElement(i)->Valence);
     1709    }
     1710  }
     1711  configuration.PsiMaxNoDown = configuration.MaxPsiDouble/2 + (configuration.MaxPsiDouble % 2);
     1712  configuration.PsiMaxNoUp = configuration.MaxPsiDouble/2;
     1713  configuration.MaxPsiDouble /= 2;
     1714  configuration.PsiType = (configuration.PsiMaxNoDown == configuration.PsiMaxNoUp) ? 0 : 1;
     1715  if ((configuration.PsiType == 1) && (configuration.ProcPEPsi < 2)) {
     1716    configuration.ProcPEGamma /= 2;
     1717    configuration.ProcPEPsi *= 2;
     1718  } else {
     1719    configuration.ProcPEGamma *= configuration.ProcPEPsi;
     1720    configuration.ProcPEPsi = 1;
     1721  }
     1722  configuration.InitMaxMinStopStep = configuration.MaxMinStopStep = configuration.MaxPsiDouble;
    17231723};
    17241724
     
    17291729{
    17301730
    1731         // 1 We will parse bonds out of the dbond file created by tremolo.
    1732                         int atom1, atom2, temp;
    1733                         atom *Walker, *OtherWalker;
    1734 
    1735                                         if (!input)
    1736                                         {
    1737                                                 cout << Verbose(1) << "Opening silica failed \n";
    1738                                         };
    1739 
    1740                         *input >> ws >> atom1;
    1741                         *input >> ws >> atom2;
    1742                                         cout << Verbose(1) << "Scanning file\n";
    1743                                         while (!input->eof()) // Check whether we read everything already
    1744                                         {
    1745                                 *input >> ws >> atom1;
    1746                                 *input >> ws >> atom2;
    1747                                                 if(atom2<atom1) //Sort indices of atoms in order
    1748                                                 {
    1749                                                         temp=atom1;
    1750                                                         atom1=atom2;
    1751                                                         atom2=temp;
    1752                                                 };
    1753 
    1754                                                 Walker=start;
    1755                                                 while(Walker-> nr != atom1) // Find atom corresponding to first index
    1756                                                 {
    1757                                                         Walker = Walker->next;
    1758                                                 };
    1759                                                 OtherWalker = Walker->next;
    1760                                                 while(OtherWalker->nr != atom2) // Find atom corresponding to second index
    1761                                                 {
    1762                                                         OtherWalker= OtherWalker->next;
    1763                                                 };
    1764                                                 AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices.
    1765 
    1766                                         }
    1767 
    1768                                         CreateListOfBondsPerAtom(out);
     1731  // 1 We will parse bonds out of the dbond file created by tremolo.
     1732      int atom1, atom2, temp;
     1733      atom *Walker, *OtherWalker;
     1734
     1735          if (!input)
     1736          {
     1737            cout << Verbose(1) << "Opening silica failed \n";
     1738          };
     1739
     1740      *input >> ws >> atom1;
     1741      *input >> ws >> atom2;
     1742          cout << Verbose(1) << "Scanning file\n";
     1743          while (!input->eof()) // Check whether we read everything already
     1744          {
     1745        *input >> ws >> atom1;
     1746        *input >> ws >> atom2;
     1747            if(atom2<atom1) //Sort indices of atoms in order
     1748            {
     1749              temp=atom1;
     1750              atom1=atom2;
     1751              atom2=temp;
     1752            };
     1753
     1754            Walker=start;
     1755            while(Walker-> nr != atom1) // Find atom corresponding to first index
     1756            {
     1757              Walker = Walker->next;
     1758            };
     1759            OtherWalker = Walker->next;
     1760            while(OtherWalker->nr != atom2) // Find atom corresponding to second index
     1761            {
     1762              OtherWalker= OtherWalker->next;
     1763            };
     1764            AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices.
     1765
     1766          }
     1767
     1768          CreateListOfBondsPerAtom(out);
    17691769
    17701770};
     
    17771777 * To make it O(N log N) the function uses the linked-cell technique as follows:
    17781778 * The procedure is step-wise:
    1779  *      -# Remove every bond in list
    1780  *      -# Count the atoms in the molecule with CountAtoms()
    1781  *      -# partition cell into smaller linked cells of size \a bonddistance
    1782  *      -# put each atom into its corresponding cell
    1783  *      -# go through every cell, check the atoms therein against all possible bond partners in the 27 adjacent cells, add bond if true
    1784  *      -# create the list of bonds via CreateListOfBondsPerAtom()
    1785  *      -# correct the bond degree iteratively (single->double->triple bond)
    1786  *      -# finally print the bond list to \a *out if desired
     1779 *  -# Remove every bond in list
     1780 *  -# Count the atoms in the molecule with CountAtoms()
     1781 *  -# partition cell into smaller linked cells of size \a bonddistance
     1782 *  -# put each atom into its corresponding cell
     1783 *  -# go through every cell, check the atoms therein against all possible bond partners in the 27 adjacent cells, add bond if true
     1784 *  -# create the list of bonds via CreateListOfBondsPerAtom()
     1785 *  -# correct the bond degree iteratively (single->double->triple bond)
     1786 *  -# finally print the bond list to \a *out if desired
    17871787 * \param *out out stream for printing the matrix, NULL if no output
    17881788 * \param bonddistance length of linked cells (i.e. maximum minimal length checked)
     
    17921792{
    17931793
    1794         atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL;
    1795         int No, NoBonds, CandidateBondNo;
    1796         int NumberCells, divisor[NDIM], n[NDIM], N[NDIM], index, Index, j;
    1797         molecule **CellList;
    1798         double distance, MinDistance, MaxDistance;
    1799         double *matrix = ReturnFullMatrixforSymmetric(cell_size);
    1800         Vector x;
    1801         int FalseBondDegree = 0;
    1802 
    1803         BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem);
    1804         *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl;
    1805         // remove every bond from the list
    1806         if ((first->next != last) && (last->previous != first)) {       // there are bonds present
    1807                 cleanup(first,last);
    1808         }
    1809 
    1810         // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering)
    1811         CountAtoms(out);
    1812         *out << Verbose(1) << "AtomCount " << AtomCount << "." << endl;
    1813 
    1814         if (AtomCount != 0) {
    1815                 // 1. find divisor for each axis, such that a sphere with radius of at least bonddistance can be placed into each cell
    1816                 j=-1;
    1817                 for (int i=0;i<NDIM;i++) {
    1818                         j += i+1;
    1819                         divisor[i] = (int)floor(cell_size[j]/bonddistance); // take smaller value such that size of linked cell is at least bonddistance
    1820                         //*out << Verbose(1) << "divisor[" << i << "]   = " << divisor[i] << "." << endl;
    1821                 }
    1822                 // 2a. allocate memory for the cell list
    1823                 NumberCells = divisor[0]*divisor[1]*divisor[2];
    1824                 *out << Verbose(1) << "Allocating " << NumberCells << " cells." << endl;
    1825                 CellList = (molecule **) Malloc(sizeof(molecule *)*NumberCells, "molecule::CreateAdjacencyList - ** CellList");
    1826                 for (int i=NumberCells;i--;)
    1827                         CellList[i] = NULL;
    1828 
    1829                 // 2b. put all atoms into its corresponding list
    1830                 Walker = start;
    1831                 while(Walker->next != end) {
    1832                         Walker = Walker->next;
    1833                         //*out << Verbose(1) << "Current atom is " << *Walker << " with coordinates ";
    1834                         //Walker->x.Output(out);
    1835                         //*out << "." << endl;
    1836                         // compute the cell by the atom's coordinates
    1837                         j=-1;
    1838                         for (int i=0;i<NDIM;i++) {
    1839                                 j += i+1;
    1840                                 x.CopyVector(&(Walker->x));
    1841                                 x.KeepPeriodic(out, matrix);
    1842                                 n[i] = (int)floor(x.x[i]/cell_size[j]*(double)divisor[i]);
    1843                         }
    1844                         index = n[2] + (n[1] + n[0] * divisor[1]) * divisor[2];
    1845                         //*out << Verbose(1) << "Atom " << *Walker << " goes into cell number [" << n[0] << "," << n[1] << "," << n[2] << "] = " << index << "." << endl;
    1846                         // add copy atom to this cell
    1847                         if (CellList[index] == NULL)    // allocate molecule if not done
    1848                                 CellList[index] = new molecule(elemente);
    1849                         OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference
    1850                         //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl;
    1851                 }
    1852                 //for (int i=0;i<NumberCells;i++)
    1853                         //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl;
    1854 
    1855 
    1856                 // 3a. go through every cell
    1857                 for (N[0]=divisor[0];N[0]--;)
    1858                         for (N[1]=divisor[1];N[1]--;)
    1859                                 for (N[2]=divisor[2];N[2]--;) {
    1860                                         Index = N[2] + (N[1] + N[0] * divisor[1]) * divisor[2];
    1861                                         if (CellList[Index] != NULL) { // if there atoms in this cell
    1862                                                 //*out << Verbose(1) << "Current cell is " << Index << "." << endl;
    1863                                                 // 3b. for every atom therein
    1864                                                 Walker = CellList[Index]->start;
    1865                                                 while (Walker->next != CellList[Index]->end) {  // go through every atom
    1866                                                         Walker = Walker->next;
    1867                                                         //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl;
    1868                                                         // 3c. check for possible bond between each atom in this and every one in the 27 cells
    1869                                                         for (n[0]=-1;n[0]<=1;n[0]++)
    1870                                                                 for (n[1]=-1;n[1]<=1;n[1]++)
    1871                                                                         for (n[2]=-1;n[2]<=1;n[2]++) {
    1872                                                                                 // compute the index of this comparison cell and make it periodic
    1873                                                                                 index = ((N[2]+n[2]+divisor[2])%divisor[2]) + (((N[1]+n[1]+divisor[1])%divisor[1]) + ((N[0]+n[0]+divisor[0])%divisor[0]) * divisor[1]) * divisor[2];
    1874                                                                                 //*out << Verbose(1) << "Number of comparison cell is " << index << "." << endl;
    1875                                                                                 if (CellList[index] != NULL) {  // if there are any atoms in this cell
    1876                                                                                         OtherWalker = CellList[index]->start;
    1877                                                                                         while(OtherWalker->next != CellList[index]->end) {      // go through every atom in this cell
    1878                                                                                                 OtherWalker = OtherWalker->next;
    1879                                                                                                 //*out << Verbose(0) << "Current comparison atom is " << *OtherWalker << "." << endl;
    1880                                                                                                 /// \todo periodic check is missing here!
    1881                                                                                                 //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl;
    1882                                                                                                 MinDistance = OtherWalker->type->CovalentRadius + Walker->type->CovalentRadius;
    1883                                                                                                 MinDistance *= (IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem;
    1884                                                                                                 MaxDistance = MinDistance + BONDTHRESHOLD;
    1885                                                                                                 MinDistance -= BONDTHRESHOLD;
    1886                                                                                                 distance = OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size);
    1887                                                                                                 if ((OtherWalker->father->nr > Walker->father->nr) && (distance <= MaxDistance*MaxDistance) && (distance >= MinDistance*MinDistance)) { // create bond if distance is smaller
    1888                                                                                                         //*out << Verbose(1) << "Adding Bond between " << *Walker << " and " << *OtherWalker << " in distance " << sqrt(distance) << "." << endl;
    1889                                                                                                         AddBond(Walker->father, OtherWalker->father, 1);        // also increases molecule::BondCount
    1890                                                                                                 } else {
    1891                                                                                                         //*out << Verbose(1) << "Not Adding: Wrong label order or distance too great." << endl;
    1892                                                                                                 }
    1893                                                                                         }
    1894                                                                                 }
    1895                                                                         }
    1896                                                 }
    1897                                         }
    1898                                 }
    1899 
    1900 
    1901 
    1902                 // 4. free the cell again
    1903                 for (int i=NumberCells;i--;)
    1904                         if (CellList[i] != NULL) {
    1905                                 delete(CellList[i]);
    1906                         }
    1907                 Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList");
    1908 
    1909                 // create the adjacency list per atom
    1910                 CreateListOfBondsPerAtom(out);
    1911 
    1912                 // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees,
    1913                 // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene
    1914                 // preferred over carbon bonds). Beforehand, we had picked the first mismatching partner, which lead to oxygenes with single instead of
    1915                 // double bonds as was expected.
    1916                 if (BondCount != 0) {
    1917                         NoCyclicBonds = 0;
    1918                         *out << Verbose(1) << "Correcting Bond degree of each bond ... ";
    1919                         do {
    1920                                 No = 0; // No acts as breakup flag (if 1 we still continue)
    1921                                 Walker = start;
    1922                                 while (Walker->next != end) { // go through every atom
    1923                                         Walker = Walker->next;
    1924                                         // count valence of first partner
    1925                                         NoBonds = 0;
    1926                                         for(j=0;j<NumberOfBondsPerAtom[Walker->nr];j++)
    1927                                                 NoBonds += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;
    1928                                         *out << Verbose(3) << "Walker " << *Walker << ": " << (int)Walker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;
    1929                                         if ((int)(Walker->type->NoValenceOrbitals) > NoBonds) { // we have a mismatch, check all bonding partners for mismatch
    1930                                                 Candidate = NULL;
    1931                                                 CandidateBondNo = -1;
    1932                                                 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through each of its bond partners
    1933                                                         OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
    1934                                                         // count valence of second partner
    1935                                                         NoBonds = 0;
    1936                                                         for(j=0;j<NumberOfBondsPerAtom[OtherWalker->nr];j++)
    1937                                                                 NoBonds += ListOfBondsPerAtom[OtherWalker->nr][j]->BondDegree;
    1938                                                         *out << Verbose(3) << "OtherWalker " << *OtherWalker << ": " << (int)OtherWalker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;
    1939                                                         if ((int)(OtherWalker->type->NoValenceOrbitals) > NoBonds) { // check if possible candidate
    1940                                                                 if ((Candidate == NULL) || (NumberOfBondsPerAtom[Candidate->nr] > NumberOfBondsPerAtom[OtherWalker->nr])) { // pick the one with fewer number of bonds first
    1941                                                                         Candidate = OtherWalker;
    1942                                                                         CandidateBondNo = i;
    1943                                                                         *out << Verbose(3) << "New candidate is " << *Candidate << "." << endl;
    1944                                                                 }
    1945                                                         }
    1946                                                 }
    1947                                                 if ((Candidate != NULL) && (CandidateBondNo != -1)) {
    1948                                                         ListOfBondsPerAtom[Walker->nr][CandidateBondNo]->BondDegree++;
    1949                                                         *out << Verbose(2) << "Increased bond degree for bond " << *ListOfBondsPerAtom[Walker->nr][CandidateBondNo] << "." << endl;
    1950                                                 } else
    1951                                                         *out << Verbose(2) << "Could not find correct degree for atom " << *Walker << "." << endl;
    1952                                                         FalseBondDegree++;
    1953                                         }
    1954                                 }
    1955                         } while (No);
    1956                 *out << " done." << endl;
    1957                 } else
    1958                         *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl;
    1959                 *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl;
    1960 
    1961                 // output bonds for debugging (if bond chain list was correctly installed)
    1962                 *out << Verbose(1) << endl << "From contents of bond chain list:";
    1963                 bond *Binder = first;
    1964                 while(Binder->next != last) {
    1965                         Binder = Binder->next;
    1966                         *out << *Binder << "\t" << endl;
    1967                 }
    1968                 *out << endl;
    1969         } else
    1970                 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl;
    1971         *out << Verbose(0) << "End of CreateAdjacencyList." << endl;
    1972         Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix");
     1794  atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL;
     1795  int No, NoBonds, CandidateBondNo;
     1796  int NumberCells, divisor[NDIM], n[NDIM], N[NDIM], index, Index, j;
     1797  molecule **CellList;
     1798  double distance, MinDistance, MaxDistance;
     1799  double *matrix = ReturnFullMatrixforSymmetric(cell_size);
     1800  Vector x;
     1801  int FalseBondDegree = 0;
     1802
     1803  BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem);
     1804  *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl;
     1805  // remove every bond from the list
     1806  if ((first->next != last) && (last->previous != first)) {  // there are bonds present
     1807    cleanup(first,last);
     1808  }
     1809
     1810  // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering)
     1811  CountAtoms(out);
     1812  *out << Verbose(1) << "AtomCount " << AtomCount << "." << endl;
     1813
     1814  if (AtomCount != 0) {
     1815    // 1. find divisor for each axis, such that a sphere with radius of at least bonddistance can be placed into each cell
     1816    j=-1;
     1817    for (int i=0;i<NDIM;i++) {
     1818      j += i+1;
     1819      divisor[i] = (int)floor(cell_size[j]/bonddistance); // take smaller value such that size of linked cell is at least bonddistance
     1820      //*out << Verbose(1) << "divisor[" << i << "]  = " << divisor[i] << "." << endl;
     1821    }
     1822    // 2a. allocate memory for the cell list
     1823    NumberCells = divisor[0]*divisor[1]*divisor[2];
     1824    *out << Verbose(1) << "Allocating " << NumberCells << " cells." << endl;
     1825    CellList = (molecule **) Malloc(sizeof(molecule *)*NumberCells, "molecule::CreateAdjacencyList - ** CellList");
     1826    for (int i=NumberCells;i--;)
     1827      CellList[i] = NULL;
     1828
     1829    // 2b. put all atoms into its corresponding list
     1830    Walker = start;
     1831    while(Walker->next != end) {
     1832      Walker = Walker->next;
     1833      //*out << Verbose(1) << "Current atom is " << *Walker << " with coordinates ";
     1834      //Walker->x.Output(out);
     1835      //*out << "." << endl;
     1836      // compute the cell by the atom's coordinates
     1837      j=-1;
     1838      for (int i=0;i<NDIM;i++) {
     1839        j += i+1;
     1840        x.CopyVector(&(Walker->x));
     1841        x.KeepPeriodic(out, matrix);
     1842        n[i] = (int)floor(x.x[i]/cell_size[j]*(double)divisor[i]);
     1843      }
     1844      index = n[2] + (n[1] + n[0] * divisor[1]) * divisor[2];
     1845      //*out << Verbose(1) << "Atom " << *Walker << " goes into cell number [" << n[0] << "," << n[1] << "," << n[2] << "] = " << index << "." << endl;
     1846      // add copy atom to this cell
     1847      if (CellList[index] == NULL)  // allocate molecule if not done
     1848        CellList[index] = new molecule(elemente);
     1849      OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference
     1850      //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl;
     1851    }
     1852    //for (int i=0;i<NumberCells;i++)
     1853      //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl;
     1854
     1855
     1856    // 3a. go through every cell
     1857    for (N[0]=divisor[0];N[0]--;)
     1858      for (N[1]=divisor[1];N[1]--;)
     1859        for (N[2]=divisor[2];N[2]--;) {
     1860          Index = N[2] + (N[1] + N[0] * divisor[1]) * divisor[2];
     1861          if (CellList[Index] != NULL) { // if there atoms in this cell
     1862            //*out << Verbose(1) << "Current cell is " << Index << "." << endl;
     1863            // 3b. for every atom therein
     1864            Walker = CellList[Index]->start;
     1865            while (Walker->next != CellList[Index]->end) {  // go through every atom
     1866              Walker = Walker->next;
     1867              //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl;
     1868              // 3c. check for possible bond between each atom in this and every one in the 27 cells
     1869              for (n[0]=-1;n[0]<=1;n[0]++)
     1870                for (n[1]=-1;n[1]<=1;n[1]++)
     1871                  for (n[2]=-1;n[2]<=1;n[2]++) {
     1872                    // compute the index of this comparison cell and make it periodic
     1873                    index = ((N[2]+n[2]+divisor[2])%divisor[2]) + (((N[1]+n[1]+divisor[1])%divisor[1]) + ((N[0]+n[0]+divisor[0])%divisor[0]) * divisor[1]) * divisor[2];
     1874                    //*out << Verbose(1) << "Number of comparison cell is " << index << "." << endl;
     1875                    if (CellList[index] != NULL) {  // if there are any atoms in this cell
     1876                      OtherWalker = CellList[index]->start;
     1877                      while(OtherWalker->next != CellList[index]->end) {  // go through every atom in this cell
     1878                        OtherWalker = OtherWalker->next;
     1879                        //*out << Verbose(0) << "Current comparison atom is " << *OtherWalker << "." << endl;
     1880                        /// \todo periodic check is missing here!
     1881                        //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl;
     1882                        MinDistance = OtherWalker->type->CovalentRadius + Walker->type->CovalentRadius;
     1883                        MinDistance *= (IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem;
     1884                        MaxDistance = MinDistance + BONDTHRESHOLD;
     1885                        MinDistance -= BONDTHRESHOLD;
     1886                        distance = OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size);
     1887                        if ((OtherWalker->father->nr > Walker->father->nr) && (distance <= MaxDistance*MaxDistance) && (distance >= MinDistance*MinDistance)) { // create bond if distance is smaller
     1888                          //*out << Verbose(1) << "Adding Bond between " << *Walker << " and " << *OtherWalker << " in distance " << sqrt(distance) << "." << endl;
     1889                          AddBond(Walker->father, OtherWalker->father, 1);  // also increases molecule::BondCount
     1890                        } else {
     1891                          //*out << Verbose(1) << "Not Adding: Wrong label order or distance too great." << endl;
     1892                        }
     1893                      }
     1894                    }
     1895                  }
     1896            }
     1897          }
     1898        }
     1899
     1900
     1901
     1902    // 4. free the cell again
     1903    for (int i=NumberCells;i--;)
     1904      if (CellList[i] != NULL) {
     1905        delete(CellList[i]);
     1906      }
     1907    Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList");
     1908
     1909    // create the adjacency list per atom
     1910    CreateListOfBondsPerAtom(out);
     1911
     1912    // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees,
     1913    // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene
     1914    // preferred over carbon bonds). Beforehand, we had picked the first mismatching partner, which lead to oxygenes with single instead of
     1915    // double bonds as was expected.
     1916    if (BondCount != 0) {
     1917      NoCyclicBonds = 0;
     1918      *out << Verbose(1) << "Correcting Bond degree of each bond ... ";
     1919      do {
     1920        No = 0; // No acts as breakup flag (if 1 we still continue)
     1921        Walker = start;
     1922        while (Walker->next != end) { // go through every atom
     1923          Walker = Walker->next;
     1924          // count valence of first partner
     1925          NoBonds = 0;
     1926          for(j=0;j<NumberOfBondsPerAtom[Walker->nr];j++)
     1927            NoBonds += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;
     1928          *out << Verbose(3) << "Walker " << *Walker << ": " << (int)Walker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;
     1929          if ((int)(Walker->type->NoValenceOrbitals) > NoBonds) { // we have a mismatch, check all bonding partners for mismatch
     1930            Candidate = NULL;
     1931            CandidateBondNo = -1;
     1932            for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through each of its bond partners
     1933              OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
     1934              // count valence of second partner
     1935              NoBonds = 0;
     1936              for(j=0;j<NumberOfBondsPerAtom[OtherWalker->nr];j++)
     1937                NoBonds += ListOfBondsPerAtom[OtherWalker->nr][j]->BondDegree;
     1938              *out << Verbose(3) << "OtherWalker " << *OtherWalker << ": " << (int)OtherWalker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;
     1939              if ((int)(OtherWalker->type->NoValenceOrbitals) > NoBonds) { // check if possible candidate
     1940                if ((Candidate == NULL) || (NumberOfBondsPerAtom[Candidate->nr] > NumberOfBondsPerAtom[OtherWalker->nr])) { // pick the one with fewer number of bonds first
     1941                  Candidate = OtherWalker;
     1942                  CandidateBondNo = i;
     1943                  *out << Verbose(3) << "New candidate is " << *Candidate << "." << endl;
     1944                }
     1945              }
     1946            }
     1947            if ((Candidate != NULL) && (CandidateBondNo != -1)) {
     1948              ListOfBondsPerAtom[Walker->nr][CandidateBondNo]->BondDegree++;
     1949              *out << Verbose(2) << "Increased bond degree for bond " << *ListOfBondsPerAtom[Walker->nr][CandidateBondNo] << "." << endl;
     1950            } else
     1951              *out << Verbose(2) << "Could not find correct degree for atom " << *Walker << "." << endl;
     1952              FalseBondDegree++;
     1953          }
     1954        }
     1955      } while (No);
     1956    *out << " done." << endl;
     1957    } else
     1958      *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl;
     1959    *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl;
     1960
     1961    // output bonds for debugging (if bond chain list was correctly installed)
     1962    *out << Verbose(1) << endl << "From contents of bond chain list:";
     1963    bond *Binder = first;
     1964    while(Binder->next != last) {
     1965      Binder = Binder->next;
     1966      *out << *Binder << "\t" << endl;
     1967    }
     1968    *out << endl;
     1969  } else
     1970    *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl;
     1971  *out << Verbose(0) << "End of CreateAdjacencyList." << endl;
     1972  Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix");
    19731973
    19741974};
     
    19861986MoleculeLeafClass * molecule::DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack)
    19871987{
    1988         class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);
    1989         BackEdgeStack = new StackClass<bond *> (BondCount);
    1990         MoleculeLeafClass *SubGraphs = new MoleculeLeafClass(NULL);
    1991         MoleculeLeafClass *LeafWalker = SubGraphs;
    1992         int CurrentGraphNr = 0, OldGraphNr;
    1993         int ComponentNumber = 0;
    1994         atom *Walker = NULL, *OtherAtom = NULL, *Root = start->next;
    1995         bond *Binder = NULL;
    1996         bool BackStepping = false;
    1997 
    1998         *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl;
    1999 
    2000         ResetAllBondsToUnused();
    2001         ResetAllAtomNumbers();
    2002         InitComponentNumbers();
    2003         BackEdgeStack->ClearStack();
    2004         while (Root != end) { // if there any atoms at all
    2005                 // (1) mark all edges unused, empty stack, set atom->GraphNr = 0 for all
    2006                 AtomStack->ClearStack();
    2007 
    2008                 // put into new subgraph molecule and add this to list of subgraphs
    2009                 LeafWalker = new MoleculeLeafClass(LeafWalker);
    2010                 LeafWalker->Leaf = new molecule(elemente);
    2011                 LeafWalker->Leaf->AddCopyAtom(Root);
    2012 
    2013                 OldGraphNr = CurrentGraphNr;
    2014                 Walker = Root;
    2015                 do { // (10)
    2016                         do { // (2) set number and Lowpoint of Atom to i, increase i, push current atom
    2017                                 if (!BackStepping) { // if we don't just return from (8)
    2018                                         Walker->GraphNr = CurrentGraphNr;
    2019                                         Walker->LowpointNr = CurrentGraphNr;
    2020                                         *out << Verbose(1) << "Setting Walker[" << Walker->Name << "]'s number to " << Walker->GraphNr << " with Lowpoint " << Walker->LowpointNr << "." << endl;
    2021                                         AtomStack->Push(Walker);
    2022                                         CurrentGraphNr++;
    2023                                 }
    2024                                 do { // (3) if Walker has no unused egdes, go to (5)
    2025                                         BackStepping = false; // reset backstepping flag for (8)
    2026                                         if (Binder == NULL) // if we don't just return from (11), Binder is already set to next unused
    2027                                                 Binder = FindNextUnused(Walker);
    2028                                         if (Binder == NULL)
    2029                                                 break;
    2030                                         *out << Verbose(2) << "Current Unused Bond is " << *Binder << "." << endl;
    2031                                         // (4) Mark Binder used, ...
    2032                                         Binder->MarkUsed(black);
    2033                                         OtherAtom = Binder->GetOtherAtom(Walker);
    2034                                         *out << Verbose(2) << "(4) OtherAtom is " << OtherAtom->Name << "." << endl;
    2035                                         if (OtherAtom->GraphNr != -1) {
    2036                                                 // (4a) ... if "other" atom has been visited (GraphNr != 0), set lowpoint to minimum of both, go to (3)
    2037                                                 Binder->Type = BackEdge;
    2038                                                 BackEdgeStack->Push(Binder);
    2039                                                 Walker->LowpointNr = ( Walker->LowpointNr < OtherAtom->GraphNr ) ? Walker->LowpointNr : OtherAtom->GraphNr;
    2040                                                 *out << Verbose(3) << "(4a) Visited: Setting Lowpoint of Walker[" << Walker->Name << "] to " << Walker->LowpointNr << "." << endl;
    2041                                         } else {
    2042                                                 // (4b) ... otherwise set OtherAtom as Ancestor of Walker and Walker as OtherAtom, go to (2)
    2043                                                 Binder->Type = TreeEdge;
    2044                                                 OtherAtom->Ancestor = Walker;
    2045                                                 Walker = OtherAtom;
    2046                                                 *out << Verbose(3) << "(4b) Not Visited: OtherAtom[" << OtherAtom->Name << "]'s Ancestor is now " << OtherAtom->Ancestor->Name << ", Walker is OtherAtom " << OtherAtom->Name << "." << endl;
    2047                                                 break;
    2048                                         }
    2049                                         Binder = NULL;
    2050                                 } while (1);    // (3)
    2051                                 if (Binder == NULL) {
    2052                                         *out << Verbose(2) << "No more Unused Bonds." << endl;
    2053                                         break;
    2054                                 } else
    2055                                         Binder = NULL;
    2056                         } while (1);    // (2)
    2057 
    2058                         // if we came from backstepping, yet there were no more unused bonds, we end up here with no Ancestor, because Walker is Root! Then we are finished!
    2059                         if ((Walker == Root) && (Binder == NULL))
    2060                                 break;
    2061 
    2062                         // (5) if Ancestor of Walker is ...
    2063                         *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl;
    2064                         if (Walker->Ancestor->GraphNr != Root->GraphNr) {
    2065                                 // (6)  (Ancestor of Walker is not Root)
    2066                                 if (Walker->LowpointNr < Walker->Ancestor->GraphNr) {
    2067                                         // (6a) set Ancestor's Lowpoint number to minimum of of its Ancestor and itself, go to Step(8)
    2068                                         Walker->Ancestor->LowpointNr = (Walker->Ancestor->LowpointNr < Walker->LowpointNr) ? Walker->Ancestor->LowpointNr : Walker->LowpointNr;
    2069                                         *out << Verbose(2) << "(6) Setting Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s Lowpoint to " << Walker->Ancestor->LowpointNr << "." << endl;
    2070                                 } else {
    2071                                         // (7) (Ancestor of Walker is a separating vertex, remove all from stack till Walker (including), these and Ancestor form a component
    2072                                         Walker->Ancestor->SeparationVertex = true;
    2073                                         *out << Verbose(2) << "(7) Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s is a separating vertex, creating component." << endl;
    2074                                         SetNextComponentNumber(Walker->Ancestor, ComponentNumber);
    2075                                         *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Ancestor's Compont is " << ComponentNumber << "." << endl;
    2076                                         SetNextComponentNumber(Walker, ComponentNumber);
    2077                                         *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Compont is " << ComponentNumber << "." << endl;
    2078                                         do {
    2079                                                 OtherAtom = AtomStack->PopLast();
    2080                                                 LeafWalker->Leaf->AddCopyAtom(OtherAtom);
    2081                                                 SetNextComponentNumber(OtherAtom, ComponentNumber);
    2082                                                 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;
    2083                                         } while (OtherAtom != Walker);
    2084                                         ComponentNumber++;
    2085                                 }
    2086                                 // (8) Walker becomes its Ancestor, go to (3)
    2087                                 *out << Verbose(2) << "(8) Walker[" << Walker->Name << "] is now its Ancestor " << Walker->Ancestor->Name << ", backstepping. " << endl;
    2088                                 Walker = Walker->Ancestor;
    2089                                 BackStepping = true;
    2090                         }
    2091                         if (!BackStepping) {    // coming from (8) want to go to (3)
    2092                                 // (9) remove all from stack till Walker (including), these and Root form a component
    2093                                 AtomStack->Output(out);
    2094                                 SetNextComponentNumber(Root, ComponentNumber);
    2095                                 *out << Verbose(3) << "(9) Root[" << Root->Name << "]'s Component is " << ComponentNumber << "." << endl;
    2096                                 SetNextComponentNumber(Walker, ComponentNumber);
    2097                                 *out << Verbose(3) << "(9) Walker[" << Walker->Name << "]'s Component is " << ComponentNumber << "." << endl;
    2098                                 do {
    2099                                         OtherAtom = AtomStack->PopLast();
    2100                                         LeafWalker->Leaf->AddCopyAtom(OtherAtom);
    2101                                         SetNextComponentNumber(OtherAtom, ComponentNumber);
    2102                                         *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;
    2103                                 } while (OtherAtom != Walker);
    2104                                 ComponentNumber++;
    2105 
    2106                                 // (11) Root is separation vertex,      set Walker to Root and go to (4)
    2107                                 Walker = Root;
    2108                                 Binder = FindNextUnused(Walker);
    2109                                 *out << Verbose(1) << "(10) Walker is Root[" << Root->Name << "], next Unused Bond is " << Binder << "." << endl;
    2110                                 if (Binder != NULL) { // Root is separation vertex
    2111                                         *out << Verbose(1) << "(11) Root is a separation vertex." << endl;
    2112                                         Walker->SeparationVertex = true;
    2113                                 }
    2114                         }
    2115                 } while ((BackStepping) || (Binder != NULL)); // (10) halt only if Root has no unused edges
    2116 
    2117                 // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph
    2118                 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl;
    2119                 LeafWalker->Leaf->Output(out);
    2120                 *out << endl;
    2121 
    2122                 // step on to next root
    2123                 while ((Root != end) && (Root->GraphNr != -1)) {
    2124                         //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl;
    2125                         if (Root->GraphNr != -1) // if already discovered, step on
    2126                                 Root = Root->next;
    2127                 }
    2128         }
    2129         // set cyclic bond criterium on "same LP" basis
    2130         Binder = first;
    2131         while(Binder->next != last) {
    2132                 Binder = Binder->next;
    2133                 if (Binder->rightatom->LowpointNr == Binder->leftatom->LowpointNr) { // cyclic ??
    2134                         Binder->Cyclic = true;
    2135                         NoCyclicBonds++;
    2136                 }
    2137         }
    2138 
    2139 
    2140         *out << Verbose(1) << "Final graph info for each atom is:" << endl;
    2141         Walker = start;
    2142         while (Walker->next != end) {
    2143                 Walker = Walker->next;
    2144                 *out << Verbose(2) << "Atom " << Walker->Name << " is " << ((Walker->SeparationVertex) ? "a" : "not a") << " separation vertex, components are ";
    2145                 OutputComponentNumber(out, Walker);
    2146                 *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl;
    2147         }
    2148 
    2149         *out << Verbose(1) << "Final graph info for each bond is:" << endl;
    2150         Binder = first;
    2151         while(Binder->next != last) {
    2152                 Binder = Binder->next;
    2153                 *out << Verbose(2) << ((Binder->Type == TreeEdge) ? "TreeEdge " : "BackEdge ") << *Binder << ": <";
    2154                 *out << ((Binder->leftatom->SeparationVertex) ? "SP," : "") << "L" << Binder->leftatom->LowpointNr << " G" << Binder->leftatom->GraphNr << " Comp.";
    2155                 OutputComponentNumber(out, Binder->leftatom);
    2156                 *out << " ===   ";
    2157                 *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp.";
    2158                 OutputComponentNumber(out, Binder->rightatom);
    2159                 *out << ">." << endl;
    2160                 if (Binder->Cyclic) // cyclic ??
    2161                         *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl;
    2162         }
    2163 
    2164         // free all and exit
    2165         delete(AtomStack);
    2166         *out << Verbose(0) << "End of DepthFirstSearchAnalysis" << endl;
    2167         return SubGraphs;
     1988  class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);
     1989  BackEdgeStack = new StackClass<bond *> (BondCount);
     1990  MoleculeLeafClass *SubGraphs = new MoleculeLeafClass(NULL);
     1991  MoleculeLeafClass *LeafWalker = SubGraphs;
     1992  int CurrentGraphNr = 0, OldGraphNr;
     1993  int ComponentNumber = 0;
     1994  atom *Walker = NULL, *OtherAtom = NULL, *Root = start->next;
     1995  bond *Binder = NULL;
     1996  bool BackStepping = false;
     1997
     1998  *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl;
     1999
     2000  ResetAllBondsToUnused();
     2001  ResetAllAtomNumbers();
     2002  InitComponentNumbers();
     2003  BackEdgeStack->ClearStack();
     2004  while (Root != end) { // if there any atoms at all
     2005    // (1) mark all edges unused, empty stack, set atom->GraphNr = 0 for all
     2006    AtomStack->ClearStack();
     2007
     2008    // put into new subgraph molecule and add this to list of subgraphs
     2009    LeafWalker = new MoleculeLeafClass(LeafWalker);
     2010    LeafWalker->Leaf = new molecule(elemente);
     2011    LeafWalker->Leaf->AddCopyAtom(Root);
     2012
     2013    OldGraphNr = CurrentGraphNr;
     2014    Walker = Root;
     2015    do { // (10)
     2016      do { // (2) set number and Lowpoint of Atom to i, increase i, push current atom
     2017        if (!BackStepping) { // if we don't just return from (8)
     2018          Walker->GraphNr = CurrentGraphNr;
     2019          Walker->LowpointNr = CurrentGraphNr;
     2020          *out << Verbose(1) << "Setting Walker[" << Walker->Name << "]'s number to " << Walker->GraphNr << " with Lowpoint " << Walker->LowpointNr << "." << endl;
     2021          AtomStack->Push(Walker);
     2022          CurrentGraphNr++;
     2023        }
     2024        do { // (3) if Walker has no unused egdes, go to (5)
     2025          BackStepping = false; // reset backstepping flag for (8)
     2026          if (Binder == NULL) // if we don't just return from (11), Binder is already set to next unused
     2027            Binder = FindNextUnused(Walker);
     2028          if (Binder == NULL)
     2029            break;
     2030          *out << Verbose(2) << "Current Unused Bond is " << *Binder << "." << endl;
     2031          // (4) Mark Binder used, ...
     2032          Binder->MarkUsed(black);
     2033          OtherAtom = Binder->GetOtherAtom(Walker);
     2034          *out << Verbose(2) << "(4) OtherAtom is " << OtherAtom->Name << "." << endl;
     2035          if (OtherAtom->GraphNr != -1) {
     2036            // (4a) ... if "other" atom has been visited (GraphNr != 0), set lowpoint to minimum of both, go to (3)
     2037            Binder->Type = BackEdge;
     2038            BackEdgeStack->Push(Binder);
     2039            Walker->LowpointNr = ( Walker->LowpointNr < OtherAtom->GraphNr ) ? Walker->LowpointNr : OtherAtom->GraphNr;
     2040            *out << Verbose(3) << "(4a) Visited: Setting Lowpoint of Walker[" << Walker->Name << "] to " << Walker->LowpointNr << "." << endl;
     2041          } else {
     2042            // (4b) ... otherwise set OtherAtom as Ancestor of Walker and Walker as OtherAtom, go to (2)
     2043            Binder->Type = TreeEdge;
     2044            OtherAtom->Ancestor = Walker;
     2045            Walker = OtherAtom;
     2046            *out << Verbose(3) << "(4b) Not Visited: OtherAtom[" << OtherAtom->Name << "]'s Ancestor is now " << OtherAtom->Ancestor->Name << ", Walker is OtherAtom " << OtherAtom->Name << "." << endl;
     2047            break;
     2048          }
     2049          Binder = NULL;
     2050        } while (1);  // (3)
     2051        if (Binder == NULL) {
     2052          *out << Verbose(2) << "No more Unused Bonds." << endl;
     2053          break;
     2054        } else
     2055          Binder = NULL;
     2056      } while (1);  // (2)
     2057
     2058      // if we came from backstepping, yet there were no more unused bonds, we end up here with no Ancestor, because Walker is Root! Then we are finished!
     2059      if ((Walker == Root) && (Binder == NULL))
     2060        break;
     2061
     2062      // (5) if Ancestor of Walker is ...
     2063      *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl;
     2064      if (Walker->Ancestor->GraphNr != Root->GraphNr) {
     2065        // (6)  (Ancestor of Walker is not Root)
     2066        if (Walker->LowpointNr < Walker->Ancestor->GraphNr) {
     2067          // (6a) set Ancestor's Lowpoint number to minimum of of its Ancestor and itself, go to Step(8)
     2068          Walker->Ancestor->LowpointNr = (Walker->Ancestor->LowpointNr < Walker->LowpointNr) ? Walker->Ancestor->LowpointNr : Walker->LowpointNr;
     2069          *out << Verbose(2) << "(6) Setting Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s Lowpoint to " << Walker->Ancestor->LowpointNr << "." << endl;
     2070        } else {
     2071          // (7) (Ancestor of Walker is a separating vertex, remove all from stack till Walker (including), these and Ancestor form a component
     2072          Walker->Ancestor->SeparationVertex = true;
     2073          *out << Verbose(2) << "(7) Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s is a separating vertex, creating component." << endl;
     2074          SetNextComponentNumber(Walker->Ancestor, ComponentNumber);
     2075          *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Ancestor's Compont is " << ComponentNumber << "." << endl;
     2076          SetNextComponentNumber(Walker, ComponentNumber);
     2077          *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Compont is " << ComponentNumber << "." << endl;
     2078          do {
     2079            OtherAtom = AtomStack->PopLast();
     2080            LeafWalker->Leaf->AddCopyAtom(OtherAtom);
     2081            SetNextComponentNumber(OtherAtom, ComponentNumber);
     2082            *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;
     2083          } while (OtherAtom != Walker);
     2084          ComponentNumber++;
     2085        }
     2086        // (8) Walker becomes its Ancestor, go to (3)
     2087        *out << Verbose(2) << "(8) Walker[" << Walker->Name << "] is now its Ancestor " << Walker->Ancestor->Name << ", backstepping. " << endl;
     2088        Walker = Walker->Ancestor;
     2089        BackStepping = true;
     2090      }
     2091      if (!BackStepping) {  // coming from (8) want to go to (3)
     2092        // (9) remove all from stack till Walker (including), these and Root form a component
     2093        AtomStack->Output(out);
     2094        SetNextComponentNumber(Root, ComponentNumber);
     2095        *out << Verbose(3) << "(9) Root[" << Root->Name << "]'s Component is " << ComponentNumber << "." << endl;
     2096        SetNextComponentNumber(Walker, ComponentNumber);
     2097        *out << Verbose(3) << "(9) Walker[" << Walker->Name << "]'s Component is " << ComponentNumber << "." << endl;
     2098        do {
     2099          OtherAtom = AtomStack->PopLast();
     2100          LeafWalker->Leaf->AddCopyAtom(OtherAtom);
     2101          SetNextComponentNumber(OtherAtom, ComponentNumber);
     2102          *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;
     2103        } while (OtherAtom != Walker);
     2104        ComponentNumber++;
     2105
     2106        // (11) Root is separation vertex,  set Walker to Root and go to (4)
     2107        Walker = Root;
     2108        Binder = FindNextUnused(Walker);
     2109        *out << Verbose(1) << "(10) Walker is Root[" << Root->Name << "], next Unused Bond is " << Binder << "." << endl;
     2110        if (Binder != NULL) { // Root is separation vertex
     2111          *out << Verbose(1) << "(11) Root is a separation vertex." << endl;
     2112          Walker->SeparationVertex = true;
     2113        }
     2114      }
     2115    } while ((BackStepping) || (Binder != NULL)); // (10) halt only if Root has no unused edges
     2116
     2117    // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph
     2118    *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl;
     2119    LeafWalker->Leaf->Output(out);
     2120    *out << endl;
     2121
     2122    // step on to next root
     2123    while ((Root != end) && (Root->GraphNr != -1)) {
     2124      //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl;
     2125      if (Root->GraphNr != -1) // if already discovered, step on
     2126        Root = Root->next;
     2127    }
     2128  }
     2129  // set cyclic bond criterium on "same LP" basis
     2130  Binder = first;
     2131  while(Binder->next != last) {
     2132    Binder = Binder->next;
     2133    if (Binder->rightatom->LowpointNr == Binder->leftatom->LowpointNr) { // cyclic ??
     2134      Binder->Cyclic = true;
     2135      NoCyclicBonds++;
     2136    }
     2137  }
     2138
     2139
     2140  *out << Verbose(1) << "Final graph info for each atom is:" << endl;
     2141  Walker = start;
     2142  while (Walker->next != end) {
     2143    Walker = Walker->next;
     2144    *out << Verbose(2) << "Atom " << Walker->Name << " is " << ((Walker->SeparationVertex) ? "a" : "not a") << " separation vertex, components are ";
     2145    OutputComponentNumber(out, Walker);
     2146    *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl;
     2147  }
     2148
     2149  *out << Verbose(1) << "Final graph info for each bond is:" << endl;
     2150  Binder = first;
     2151  while(Binder->next != last) {
     2152    Binder = Binder->next;
     2153    *out << Verbose(2) << ((Binder->Type == TreeEdge) ? "TreeEdge " : "BackEdge ") << *Binder << ": <";
     2154    *out << ((Binder->leftatom->SeparationVertex) ? "SP," : "") << "L" << Binder->leftatom->LowpointNr << " G" << Binder->leftatom->GraphNr << " Comp.";
     2155    OutputComponentNumber(out, Binder->leftatom);
     2156    *out << " ===  ";
     2157    *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp.";
     2158    OutputComponentNumber(out, Binder->rightatom);
     2159    *out << ">." << endl;
     2160    if (Binder->Cyclic) // cyclic ??
     2161      *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl;
     2162  }
     2163
     2164  // free all and exit
     2165  delete(AtomStack);
     2166  *out << Verbose(0) << "End of DepthFirstSearchAnalysis" << endl;
     2167  return SubGraphs;
    21682168};
    21692169
     
    21782178 * \todo BFS from the not-same-LP to find back to starting point of tributary cycle over more than one bond
    21792179 */
    2180 void molecule::CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> *        BackEdgeStack, int *&MinimumRingSize)
    2181 {
    2182         atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CyclicStructureAnalysis: **PredecessorList");
    2183         int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList");
    2184         enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList");
    2185         class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount);        // will hold the current ring
    2186         class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount);    // contains all "touched" atoms (that need to be reset after BFS loop)
    2187         atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL;
    2188         bond *Binder = NULL, *BackEdge = NULL;
    2189         int RingSize, NumCycles, MinRingSize = -1;
    2190 
    2191         // initialise each vertex as white with no predecessor, empty queue, color Root lightgray
    2192         for (int i=AtomCount;i--;) {
    2193                 PredecessorList[i] = NULL;
    2194                 ShortestPathList[i] = -1;
    2195                 ColorList[i] = white;
    2196         }
    2197 
    2198         *out << Verbose(1) << "Back edge list - ";
    2199         BackEdgeStack->Output(out);
    2200 
    2201         *out << Verbose(1) << "Analysing cycles ... " << endl;
    2202         NumCycles = 0;
    2203         while (!BackEdgeStack->IsEmpty()) {
    2204                 BackEdge = BackEdgeStack->PopFirst();
    2205                 // this is the target
    2206                 Root = BackEdge->leftatom;
    2207                 // this is the source point
    2208                 Walker = BackEdge->rightatom;
    2209                 ShortestPathList[Walker->nr] = 0;
    2210                 BFSStack->ClearStack(); // start with empty BFS stack
    2211                 BFSStack->Push(Walker);
    2212                 TouchedStack->Push(Walker);
    2213                 *out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;
    2214                 OtherAtom = NULL;
    2215                 do {    // look for Root
    2216                         Walker = BFSStack->PopFirst();
    2217                         *out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;
    2218                         for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
    2219                                 Binder = ListOfBondsPerAtom[Walker->nr][i];
    2220                                 if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder)
    2221                                         OtherAtom = Binder->GetOtherAtom(Walker);
     2180void molecule::CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> *  BackEdgeStack, int *&MinimumRingSize)
     2181{
     2182  atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CyclicStructureAnalysis: **PredecessorList");
     2183  int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList");
     2184  enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList");
     2185  class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount);  // will hold the current ring
     2186  class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount);  // contains all "touched" atoms (that need to be reset after BFS loop)
     2187  atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL;
     2188  bond *Binder = NULL, *BackEdge = NULL;
     2189  int RingSize, NumCycles, MinRingSize = -1;
     2190
     2191  // initialise each vertex as white with no predecessor, empty queue, color Root lightgray
     2192  for (int i=AtomCount;i--;) {
     2193    PredecessorList[i] = NULL;
     2194    ShortestPathList[i] = -1;
     2195    ColorList[i] = white;
     2196  }
     2197
     2198  *out << Verbose(1) << "Back edge list - ";
     2199  BackEdgeStack->Output(out);
     2200
     2201  *out << Verbose(1) << "Analysing cycles ... " << endl;
     2202  NumCycles = 0;
     2203  while (!BackEdgeStack->IsEmpty()) {
     2204    BackEdge = BackEdgeStack->PopFirst();
     2205    // this is the target
     2206    Root = BackEdge->leftatom;
     2207    // this is the source point
     2208    Walker = BackEdge->rightatom;
     2209    ShortestPathList[Walker->nr] = 0;
     2210    BFSStack->ClearStack();  // start with empty BFS stack
     2211    BFSStack->Push(Walker);
     2212    TouchedStack->Push(Walker);
     2213    *out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;
     2214    OtherAtom = NULL;
     2215    do {  // look for Root
     2216      Walker = BFSStack->PopFirst();
     2217      *out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;
     2218      for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
     2219        Binder = ListOfBondsPerAtom[Walker->nr][i];
     2220        if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder)
     2221          OtherAtom = Binder->GetOtherAtom(Walker);
    22222222#ifdef ADDHYDROGEN
    2223                                         if (OtherAtom->type->Z != 1) {
     2223          if (OtherAtom->type->Z != 1) {
    22242224#endif
    2225                                                 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
    2226                                                 if (ColorList[OtherAtom->nr] == white) {
    2227                                                         TouchedStack->Push(OtherAtom);
    2228                                                         ColorList[OtherAtom->nr] = lightgray;
    2229                                                         PredecessorList[OtherAtom->nr] = Walker;        // Walker is the predecessor
    2230                                                         ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
    2231                                                         *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " lightgray, its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl;
    2232                                                         //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance
    2233                                                                 *out << Verbose(3) << "Putting OtherAtom into queue." << endl;
    2234                                                                 BFSStack->Push(OtherAtom);
    2235                                                         //}
    2236                                                 } else {
    2237                                                         *out << Verbose(3) << "Not Adding, has already been visited." << endl;
    2238                                                 }
    2239                                                 if (OtherAtom == Root)
    2240                                                         break;
     2225            *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
     2226            if (ColorList[OtherAtom->nr] == white) {
     2227              TouchedStack->Push(OtherAtom);
     2228              ColorList[OtherAtom->nr] = lightgray;
     2229              PredecessorList[OtherAtom->nr] = Walker;  // Walker is the predecessor
     2230              ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
     2231              *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " lightgray, its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl;
     2232              //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance
     2233                *out << Verbose(3) << "Putting OtherAtom into queue." << endl;
     2234                BFSStack->Push(OtherAtom);
     2235              //}
     2236            } else {
     2237              *out << Verbose(3) << "Not Adding, has already been visited." << endl;
     2238            }
     2239            if (OtherAtom == Root)
     2240              break;
    22412241#ifdef ADDHYDROGEN
    2242                                         } else {
    2243                                                 *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl;
    2244                                                 ColorList[OtherAtom->nr] = black;
    2245                                         }
     2242          } else {
     2243            *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl;
     2244            ColorList[OtherAtom->nr] = black;
     2245          }
    22462246#endif
    2247                                 } else {
    2248                                         *out << Verbose(2) << "Bond " << *Binder << " not Visiting, is the back edge." << endl;
    2249                                 }
    2250                         }
    2251                         ColorList[Walker->nr] = black;
    2252                         *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
    2253                         if (OtherAtom == Root) { // if we have found the root, check whether this cycle wasn't already found beforehand
    2254                                 // step through predecessor list
    2255                                 while (OtherAtom != BackEdge->rightatom) {
    2256                                         if (!OtherAtom->GetTrueFather()->IsCyclic)      // if one bond in the loop is not marked as cyclic, we haven't found this cycle yet
    2257                                                 break;
    2258                                         else
    2259                                                 OtherAtom = PredecessorList[OtherAtom->nr];
    2260                                 }
    2261                                 if (OtherAtom == BackEdge->rightatom) { // if each atom in found cycle is cyclic, loop's been found before already
    2262                                         *out << Verbose(3) << "This cycle was already found before, skipping and removing seeker from search." << endl;\
    2263                                         do {
    2264                                                 OtherAtom = TouchedStack->PopLast();
    2265                                                 if (PredecessorList[OtherAtom->nr] == Walker) {
    2266                                                         *out << Verbose(4) << "Removing " << *OtherAtom << " from lists and stacks." << endl;
    2267                                                         PredecessorList[OtherAtom->nr] = NULL;
    2268                                                         ShortestPathList[OtherAtom->nr] = -1;
    2269                                                         ColorList[OtherAtom->nr] = white;
    2270                                                         BFSStack->RemoveItem(OtherAtom);
    2271                                                 }
    2272                                         } while ((!TouchedStack->IsEmpty()) && (PredecessorList[OtherAtom->nr] == NULL));
    2273                                         TouchedStack->Push(OtherAtom);  // last was wrongly popped
    2274                                         OtherAtom = BackEdge->rightatom; // set to not Root
    2275                                 } else
    2276                                         OtherAtom = Root;
    2277                         }
    2278                 } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr])));
    2279 
    2280                 if (OtherAtom == Root) {
    2281                         // now climb back the predecessor list and thus find the cycle members
    2282                         NumCycles++;
    2283                         RingSize = 1;
    2284                         Root->GetTrueFather()->IsCyclic = true;
    2285                         *out << Verbose(1) << "Found ring contains: ";
    2286                         Walker = Root;
    2287                         while (Walker != BackEdge->rightatom) {
    2288                                 *out << Walker->Name << " <-> ";
    2289                                 Walker = PredecessorList[Walker->nr];
    2290                                 Walker->GetTrueFather()->IsCyclic = true;
    2291                                 RingSize++;
    2292                         }
    2293                         *out << Walker->Name << "       with a length of " << RingSize << "." << endl << endl;
    2294                         // walk through all and set MinimumRingSize
    2295                         Walker = Root;
    2296                         MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;
    2297                         while (Walker != BackEdge->rightatom) {
    2298                                 Walker = PredecessorList[Walker->nr];
    2299                                 if (RingSize < MinimumRingSize[Walker->GetTrueFather()->nr])
    2300                                         MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;
    2301                         }
    2302                         if ((RingSize < MinRingSize) || (MinRingSize == -1))
    2303                                 MinRingSize = RingSize;
    2304                 } else {
    2305                         *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl;
    2306                 }
    2307 
    2308                 // now clean the lists
    2309                 while (!TouchedStack->IsEmpty()){
    2310                         Walker = TouchedStack->PopFirst();
    2311                         PredecessorList[Walker->nr] = NULL;
    2312                         ShortestPathList[Walker->nr] = -1;
    2313                         ColorList[Walker->nr] = white;
    2314                 }
    2315         }
    2316         if (MinRingSize != -1) {
    2317                 // go over all atoms
    2318                 Root = start;
    2319                 while(Root->next != end) {
    2320                         Root = Root->next;
    2321 
    2322                         if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is
    2323                                 Walker = Root;
    2324                                 ShortestPathList[Walker->nr] = 0;
    2325                                 BFSStack->ClearStack(); // start with empty BFS stack
    2326                                 BFSStack->Push(Walker);
    2327                                 TouchedStack->Push(Walker);
    2328                                 //*out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;
    2329                                 OtherAtom = Walker;
    2330                                 while (OtherAtom != NULL) {     // look for Root
    2331                                         Walker = BFSStack->PopFirst();
    2332                                         //*out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;
    2333                                         for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
    2334                                                 Binder = ListOfBondsPerAtom[Walker->nr][i];
    2335                                                 if ((Binder != BackEdge) || (NumberOfBondsPerAtom[Walker->nr] == 1)) { // only walk along DFS spanning tree (otherwise we always find SP of 1 being backedge Binder), but terminal hydrogens may be connected via backedge, hence extra check
    2336                                                         OtherAtom = Binder->GetOtherAtom(Walker);
    2337                                                         //*out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
    2338                                                         if (ColorList[OtherAtom->nr] == white) {
    2339                                                                 TouchedStack->Push(OtherAtom);
    2340                                                                 ColorList[OtherAtom->nr] = lightgray;
    2341                                                                 PredecessorList[OtherAtom->nr] = Walker;        // Walker is the predecessor
    2342                                                                 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
    2343                                                                 //*out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " lightgray, its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl;
    2344                                                                 if (OtherAtom->GetTrueFather()->IsCyclic) { // if the other atom is connected to a ring
    2345                                                                         MinimumRingSize[Root->GetTrueFather()->nr] = ShortestPathList[OtherAtom->nr]+MinimumRingSize[OtherAtom->GetTrueFather()->nr];
    2346                                                                         OtherAtom = NULL; //break;
    2347                                                                         break;
    2348                                                                 } else
    2349                                                                         BFSStack->Push(OtherAtom);
    2350                                                         } else {
    2351                                                                 //*out << Verbose(3) << "Not Adding, has already been visited." << endl;
    2352                                                         }
    2353                                                 } else {
    2354                                                         //*out << Verbose(3) << "Not Visiting, is a back edge." << endl;
    2355                                                 }
    2356                                         }
    2357                                         ColorList[Walker->nr] = black;
    2358                                         //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
    2359                                 }
    2360 
    2361                                 // now clean the lists
    2362                                 while (!TouchedStack->IsEmpty()){
    2363                                         Walker = TouchedStack->PopFirst();
    2364                                         PredecessorList[Walker->nr] = NULL;
    2365                                         ShortestPathList[Walker->nr] = -1;
    2366                                         ColorList[Walker->nr] = white;
    2367                                 }
    2368                         }
    2369                         *out << Verbose(1) << "Minimum ring size of " << *Root << " is " << MinimumRingSize[Root->GetTrueFather()->nr] << "." << endl;
    2370                 }
    2371                 *out << Verbose(1) << "Minimum ring size is " << MinRingSize << ", over " << NumCycles << " cycles total." << endl;
    2372         } else
    2373                 *out << Verbose(1) << "No rings were detected in the molecular structure." << endl;
    2374 
    2375         Free((void **)&PredecessorList, "molecule::CyclicStructureAnalysis: **PredecessorList");
    2376         Free((void **)&ShortestPathList, "molecule::CyclicStructureAnalysis: **ShortestPathList");
    2377         Free((void **)&ColorList, "molecule::CyclicStructureAnalysis: **ColorList");
    2378         delete(BFSStack);
     2247        } else {
     2248          *out << Verbose(2) << "Bond " << *Binder << " not Visiting, is the back edge." << endl;
     2249        }
     2250      }
     2251      ColorList[Walker->nr] = black;
     2252      *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
     2253      if (OtherAtom == Root) { // if we have found the root, check whether this cycle wasn't already found beforehand
     2254        // step through predecessor list
     2255        while (OtherAtom != BackEdge->rightatom) {
     2256          if (!OtherAtom->GetTrueFather()->IsCyclic)  // if one bond in the loop is not marked as cyclic, we haven't found this cycle yet
     2257            break;
     2258          else
     2259            OtherAtom = PredecessorList[OtherAtom->nr];
     2260        }
     2261        if (OtherAtom == BackEdge->rightatom) { // if each atom in found cycle is cyclic, loop's been found before already
     2262          *out << Verbose(3) << "This cycle was already found before, skipping and removing seeker from search." << endl;\
     2263          do {
     2264            OtherAtom = TouchedStack->PopLast();
     2265            if (PredecessorList[OtherAtom->nr] == Walker) {
     2266              *out << Verbose(4) << "Removing " << *OtherAtom << " from lists and stacks." << endl;
     2267              PredecessorList[OtherAtom->nr] = NULL;
     2268              ShortestPathList[OtherAtom->nr] = -1;
     2269              ColorList[OtherAtom->nr] = white;
     2270              BFSStack->RemoveItem(OtherAtom);
     2271            }
     2272          } while ((!TouchedStack->IsEmpty()) && (PredecessorList[OtherAtom->nr] == NULL));
     2273          TouchedStack->Push(OtherAtom);  // last was wrongly popped
     2274          OtherAtom = BackEdge->rightatom; // set to not Root
     2275        } else
     2276          OtherAtom = Root;
     2277      }
     2278    } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr])));
     2279
     2280    if (OtherAtom == Root) {
     2281      // now climb back the predecessor list and thus find the cycle members
     2282      NumCycles++;
     2283      RingSize = 1;
     2284      Root->GetTrueFather()->IsCyclic = true;
     2285      *out << Verbose(1) << "Found ring contains: ";
     2286      Walker = Root;
     2287      while (Walker != BackEdge->rightatom) {
     2288        *out << Walker->Name << " <-> ";
     2289        Walker = PredecessorList[Walker->nr];
     2290        Walker->GetTrueFather()->IsCyclic = true;
     2291        RingSize++;
     2292      }
     2293      *out << Walker->Name << "  with a length of " << RingSize << "." << endl << endl;
     2294      // walk through all and set MinimumRingSize
     2295      Walker = Root;
     2296      MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;
     2297      while (Walker != BackEdge->rightatom) {
     2298        Walker = PredecessorList[Walker->nr];
     2299        if (RingSize < MinimumRingSize[Walker->GetTrueFather()->nr])
     2300          MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;
     2301      }
     2302      if ((RingSize < MinRingSize) || (MinRingSize == -1))
     2303        MinRingSize = RingSize;
     2304    } else {
     2305      *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl;
     2306    }
     2307
     2308    // now clean the lists
     2309    while (!TouchedStack->IsEmpty()){
     2310      Walker = TouchedStack->PopFirst();
     2311      PredecessorList[Walker->nr] = NULL;
     2312      ShortestPathList[Walker->nr] = -1;
     2313      ColorList[Walker->nr] = white;
     2314    }
     2315  }
     2316  if (MinRingSize != -1) {
     2317    // go over all atoms
     2318    Root = start;
     2319    while(Root->next != end) {
     2320      Root = Root->next;
     2321
     2322      if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is
     2323        Walker = Root;
     2324        ShortestPathList[Walker->nr] = 0;
     2325        BFSStack->ClearStack();  // start with empty BFS stack
     2326        BFSStack->Push(Walker);
     2327        TouchedStack->Push(Walker);
     2328        //*out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;
     2329        OtherAtom = Walker;
     2330        while (OtherAtom != NULL) {  // look for Root
     2331          Walker = BFSStack->PopFirst();
     2332          //*out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;
     2333          for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
     2334            Binder = ListOfBondsPerAtom[Walker->nr][i];
     2335            if ((Binder != BackEdge) || (NumberOfBondsPerAtom[Walker->nr] == 1)) { // only walk along DFS spanning tree (otherwise we always find SP of 1 being backedge Binder), but terminal hydrogens may be connected via backedge, hence extra check
     2336              OtherAtom = Binder->GetOtherAtom(Walker);
     2337              //*out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
     2338              if (ColorList[OtherAtom->nr] == white) {
     2339                TouchedStack->Push(OtherAtom);
     2340                ColorList[OtherAtom->nr] = lightgray;
     2341                PredecessorList[OtherAtom->nr] = Walker;  // Walker is the predecessor
     2342                ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
     2343                //*out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " lightgray, its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl;
     2344                if (OtherAtom->GetTrueFather()->IsCyclic) { // if the other atom is connected to a ring
     2345                  MinimumRingSize[Root->GetTrueFather()->nr] = ShortestPathList[OtherAtom->nr]+MinimumRingSize[OtherAtom->GetTrueFather()->nr];
     2346                  OtherAtom = NULL; //break;
     2347                  break;
     2348                } else
     2349                  BFSStack->Push(OtherAtom);
     2350              } else {
     2351                //*out << Verbose(3) << "Not Adding, has already been visited." << endl;
     2352              }
     2353            } else {
     2354              //*out << Verbose(3) << "Not Visiting, is a back edge." << endl;
     2355            }
     2356          }
     2357          ColorList[Walker->nr] = black;
     2358          //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
     2359        }
     2360
     2361        // now clean the lists
     2362        while (!TouchedStack->IsEmpty()){
     2363          Walker = TouchedStack->PopFirst();
     2364          PredecessorList[Walker->nr] = NULL;
     2365          ShortestPathList[Walker->nr] = -1;
     2366          ColorList[Walker->nr] = white;
     2367        }
     2368      }
     2369      *out << Verbose(1) << "Minimum ring size of " << *Root << " is " << MinimumRingSize[Root->GetTrueFather()->nr] << "." << endl;
     2370    }
     2371    *out << Verbose(1) << "Minimum ring size is " << MinRingSize << ", over " << NumCycles << " cycles total." << endl;
     2372  } else
     2373    *out << Verbose(1) << "No rings were detected in the molecular structure." << endl;
     2374
     2375  Free((void **)&PredecessorList, "molecule::CyclicStructureAnalysis: **PredecessorList");
     2376  Free((void **)&ShortestPathList, "molecule::CyclicStructureAnalysis: **ShortestPathList");
     2377  Free((void **)&ColorList, "molecule::CyclicStructureAnalysis: **ColorList");
     2378  delete(BFSStack);
    23792379};
    23802380
     
    23862386void molecule::SetNextComponentNumber(atom *vertex, int nr)
    23872387{
    2388         int i=0;
    2389         if (vertex != NULL) {
    2390                 for(;i<NumberOfBondsPerAtom[vertex->nr];i++) {
    2391                         if (vertex->ComponentNr[i] == -1) {      // check if not yet used
    2392                                 vertex->ComponentNr[i] = nr;
    2393                                 break;
    2394                         }
    2395                         else if (vertex->ComponentNr[i] == nr) // if number is already present, don't add another time
    2396                                 break;  // breaking here will not cause error!
    2397                 }
    2398                 if (i == NumberOfBondsPerAtom[vertex->nr])
    2399                         cerr << "Error: All Component entries are already occupied!" << endl;
    2400         } else
    2401                         cerr << "Error: Given vertex is NULL!" << endl;
     2388  int i=0;
     2389  if (vertex != NULL) {
     2390    for(;i<NumberOfBondsPerAtom[vertex->nr];i++) {
     2391      if (vertex->ComponentNr[i] == -1) {  // check if not yet used
     2392        vertex->ComponentNr[i] = nr;
     2393        break;
     2394      }
     2395      else if (vertex->ComponentNr[i] == nr) // if number is already present, don't add another time
     2396        break;  // breaking here will not cause error!
     2397    }
     2398    if (i == NumberOfBondsPerAtom[vertex->nr])
     2399      cerr << "Error: All Component entries are already occupied!" << endl;
     2400  } else
     2401      cerr << "Error: Given vertex is NULL!" << endl;
    24022402};
    24032403
     
    24072407void molecule::OutputComponentNumber(ofstream *out, atom *vertex)
    24082408{
    2409         for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)
    2410                 *out << vertex->ComponentNr[i] << "     ";
     2409  for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)
     2410    *out << vertex->ComponentNr[i] << "  ";
    24112411};
    24122412
     
    24152415void molecule::InitComponentNumbers()
    24162416{
    2417         atom *Walker = start;
    2418         while(Walker->next != end) {
    2419                 Walker = Walker->next;
    2420                 if (Walker->ComponentNr != NULL)
    2421                         Free((void **)&Walker->ComponentNr, "molecule::InitComponentNumbers: **Walker->ComponentNr");
    2422                 Walker->ComponentNr = (int *) Malloc(sizeof(int)*NumberOfBondsPerAtom[Walker->nr], "molecule::InitComponentNumbers: *Walker->ComponentNr");
    2423                 for (int i=NumberOfBondsPerAtom[Walker->nr];i--;)
    2424                         Walker->ComponentNr[i] = -1;
    2425         }
     2417  atom *Walker = start;
     2418  while(Walker->next != end) {
     2419    Walker = Walker->next;
     2420    if (Walker->ComponentNr != NULL)
     2421      Free((void **)&Walker->ComponentNr, "molecule::InitComponentNumbers: **Walker->ComponentNr");
     2422    Walker->ComponentNr = (int *) Malloc(sizeof(int)*NumberOfBondsPerAtom[Walker->nr], "molecule::InitComponentNumbers: *Walker->ComponentNr");
     2423    for (int i=NumberOfBondsPerAtom[Walker->nr];i--;)
     2424      Walker->ComponentNr[i] = -1;
     2425  }
    24262426};
    24272427
     
    24322432bond * molecule::FindNextUnused(atom *vertex)
    24332433{
    2434         for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)
    2435                 if (ListOfBondsPerAtom[vertex->nr][i]->IsUsed() == white)
    2436                         return(ListOfBondsPerAtom[vertex->nr][i]);
    2437         return NULL;
     2434  for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)
     2435    if (ListOfBondsPerAtom[vertex->nr][i]->IsUsed() == white)
     2436      return(ListOfBondsPerAtom[vertex->nr][i]);
     2437  return NULL;
    24382438};
    24392439
     
    24432443void molecule::ResetAllBondsToUnused()
    24442444{
    2445         bond *Binder = first;
    2446         while (Binder->next != last) {
    2447                 Binder = Binder->next;
    2448                 Binder->ResetUsed();
    2449         }
     2445  bond *Binder = first;
     2446  while (Binder->next != last) {
     2447    Binder = Binder->next;
     2448    Binder->ResetUsed();
     2449  }
    24502450};
    24512451
     
    24542454void molecule::ResetAllAtomNumbers()
    24552455{
    2456         atom *Walker = start;
    2457         while (Walker->next != end) {
    2458                 Walker = Walker->next;
    2459                 Walker->GraphNr = -1;
    2460         }
     2456  atom *Walker = start;
     2457  while (Walker->next != end) {
     2458    Walker = Walker->next;
     2459    Walker->GraphNr  = -1;
     2460  }
    24612461};
    24622462
     
    24672467void OutputAlreadyVisited(ofstream *out, int *list)
    24682468{
    2469         *out << Verbose(4) << "Already Visited Bonds:\t";
    2470         for(int i=1;i<=list[0];i++) *out << Verbose(0) << list[i] << "  ";
    2471         *out << endl;
     2469  *out << Verbose(4) << "Already Visited Bonds:\t";
     2470  for(int i=1;i<=list[0];i++) *out << Verbose(0) << list[i] << "  ";
     2471  *out << endl;
    24722472};
    24732473
     
    24752475 * The upper limit is
    24762476 * \f[
    2477  *      n = N \cdot C^k
     2477 *  n = N \cdot C^k
    24782478 * \f]
    24792479 * where \f$C=2^c\f$ and c is the maximum bond degree over N number of atoms.
     
    24842484int molecule::GuesstimateFragmentCount(ofstream *out, int order)
    24852485{
    2486         int c = 0;
    2487         int FragmentCount;
    2488         // get maximum bond degree
    2489         atom *Walker = start;
    2490         while (Walker->next != end) {
    2491                 Walker = Walker->next;
    2492                 c = (NumberOfBondsPerAtom[Walker->nr] > c) ? NumberOfBondsPerAtom[Walker->nr] : c;
    2493         }
    2494         FragmentCount = NoNonHydrogen*(1 << (c*order));
    2495         *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl;
    2496         return FragmentCount;
     2486  int c = 0;
     2487  int FragmentCount;
     2488  // get maximum bond degree
     2489  atom *Walker = start;
     2490  while (Walker->next != end) {
     2491    Walker = Walker->next;
     2492    c = (NumberOfBondsPerAtom[Walker->nr] > c) ? NumberOfBondsPerAtom[Walker->nr] : c;
     2493  }
     2494  FragmentCount = NoNonHydrogen*(1 << (c*order));
     2495  *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl;
     2496  return FragmentCount;
    24972497};
    24982498
     
    25052505bool molecule::ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet)
    25062506{
    2507         stringstream line;
    2508         int AtomNr;
    2509         int status = 0;
    2510 
    2511         line.str(buffer);
    2512         while (!line.eof()) {
    2513                 line >> AtomNr;
    2514                 if ((AtomNr >= 0) && (AtomNr < AtomCount)) {
    2515                         CurrentSet.insert(AtomNr);      // insert at end, hence in same order as in file!
    2516                         status++;
    2517                 } // else it's "-1" or else and thus must not be added
    2518         }
    2519         *out << Verbose(1) << "The scanned KeySet is ";
    2520         for(KeySet::iterator runner = CurrentSet.begin(); runner != CurrentSet.end(); runner++) {
    2521                 *out << (*runner) << "\t";
    2522         }
    2523         *out << endl;
    2524         return (status != 0);
     2507  stringstream line;
     2508  int AtomNr;
     2509  int status = 0;
     2510
     2511  line.str(buffer);
     2512  while (!line.eof()) {
     2513    line >> AtomNr;
     2514    if ((AtomNr >= 0) && (AtomNr < AtomCount)) {
     2515      CurrentSet.insert(AtomNr);  // insert at end, hence in same order as in file!
     2516      status++;
     2517    } // else it's "-1" or else and thus must not be added
     2518  }
     2519  *out << Verbose(1) << "The scanned KeySet is ";
     2520  for(KeySet::iterator runner = CurrentSet.begin(); runner != CurrentSet.end(); runner++) {
     2521    *out << (*runner) << "\t";
     2522  }
     2523  *out << endl;
     2524  return (status != 0);
    25252525};
    25262526
     
    25372537bool molecule::ParseKeySetFile(ofstream *out, char *path, Graph *&FragmentList)
    25382538{
    2539         bool status = true;
    2540         ifstream InputFile;
    2541         stringstream line;
    2542         GraphTestPair testGraphInsert;
    2543         int NumberOfFragments = 0;
    2544         double TEFactor;
    2545         char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename");
    2546 
    2547         if (FragmentList == NULL) { // check list pointer
    2548                 FragmentList = new Graph;
    2549         }
    2550 
    2551         // 1st pass: open file and read
    2552         *out << Verbose(1) << "Parsing the KeySet file ... " << endl;
    2553         sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, KEYSETFILE);
    2554         InputFile.open(filename);
    2555         if (InputFile != NULL) {
    2556                 // each line represents a new fragment
    2557                 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - *buffer");
    2558                 // 1. parse keysets and insert into temp. graph
    2559                 while (!InputFile.eof()) {
    2560                         InputFile.getline(buffer, MAXSTRINGSIZE);
    2561                         KeySet CurrentSet;
    2562                         if ((strlen(buffer) > 0) && (ScanBufferIntoKeySet(out, buffer, CurrentSet))) {  // if at least one valid atom was added, write config
    2563                                 testGraphInsert = FragmentList->insert(GraphPair (CurrentSet,pair<int,double>(NumberOfFragments++,1))); // store fragment number and current factor
    2564                                 if (!testGraphInsert.second) {
    2565                                         cerr << "KeySet file must be corrupt as there are two equal key sets therein!" << endl;
    2566                                 }
    2567                         }
    2568                 }
    2569                 // 2. Free and done
    2570                 InputFile.close();
    2571                 InputFile.clear();
    2572                 Free((void **)&buffer, "molecule::ParseKeySetFile - *buffer");
    2573                 *out << Verbose(1) << "done." << endl;
    2574         } else {
    2575                 *out << Verbose(1) << "File " << filename << " not found." << endl;
    2576                 status = false;
    2577         }
    2578 
    2579         // 2nd pass: open TEFactors file and read
    2580         *out << Verbose(1) << "Parsing the TEFactors file ... " << endl;
    2581         sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, TEFACTORSFILE);
    2582         InputFile.open(filename);
    2583         if (InputFile != NULL) {
    2584                 // 3. add found TEFactors to each keyset
    2585                 NumberOfFragments = 0;
    2586                 for(Graph::iterator runner = FragmentList->begin();runner != FragmentList->end(); runner++) {
    2587                         if (!InputFile.eof()) {
    2588                                 InputFile >> TEFactor;
    2589                                 (*runner).second.second = TEFactor;
    2590                                 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl;
    2591                         } else {
    2592                                 status = false;
    2593                                 break;
    2594                         }
    2595                 }
    2596                 // 4. Free and done
    2597                 InputFile.close();
    2598                 *out << Verbose(1) << "done." << endl;
    2599         } else {
    2600                 *out << Verbose(1) << "File " << filename << " not found." << endl;
    2601                 status = false;
    2602         }
    2603 
    2604         // free memory
    2605         Free((void **)&filename, "molecule::ParseKeySetFile - filename");
    2606 
    2607         return status;
     2539  bool status = true;
     2540  ifstream InputFile;
     2541  stringstream line;
     2542  GraphTestPair testGraphInsert;
     2543  int NumberOfFragments = 0;
     2544  double TEFactor;
     2545  char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename");
     2546
     2547  if (FragmentList == NULL) { // check list pointer
     2548    FragmentList = new Graph;
     2549  }
     2550
     2551  // 1st pass: open file and read
     2552  *out << Verbose(1) << "Parsing the KeySet file ... " << endl;
     2553  sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, KEYSETFILE);
     2554  InputFile.open(filename);
     2555  if (InputFile != NULL) {
     2556    // each line represents a new fragment
     2557    char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - *buffer");
     2558    // 1. parse keysets and insert into temp. graph
     2559    while (!InputFile.eof()) {
     2560      InputFile.getline(buffer, MAXSTRINGSIZE);
     2561      KeySet CurrentSet;
     2562      if ((strlen(buffer) > 0) && (ScanBufferIntoKeySet(out, buffer, CurrentSet))) {  // if at least one valid atom was added, write config
     2563        testGraphInsert = FragmentList->insert(GraphPair (CurrentSet,pair<int,double>(NumberOfFragments++,1)));  // store fragment number and current factor
     2564        if (!testGraphInsert.second) {
     2565          cerr << "KeySet file must be corrupt as there are two equal key sets therein!" << endl;
     2566        }
     2567      }
     2568    }
     2569    // 2. Free and done
     2570    InputFile.close();
     2571    InputFile.clear();
     2572    Free((void **)&buffer, "molecule::ParseKeySetFile - *buffer");
     2573    *out << Verbose(1) << "done." << endl;
     2574  } else {
     2575    *out << Verbose(1) << "File " << filename << " not found." << endl;
     2576    status = false;
     2577  }
     2578
     2579  // 2nd pass: open TEFactors file and read
     2580  *out << Verbose(1) << "Parsing the TEFactors file ... " << endl;
     2581  sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, TEFACTORSFILE);
     2582  InputFile.open(filename);
     2583  if (InputFile != NULL) {
     2584    // 3. add found TEFactors to each keyset
     2585    NumberOfFragments = 0;
     2586    for(Graph::iterator runner = FragmentList->begin();runner != FragmentList->end(); runner++) {
     2587      if (!InputFile.eof()) {
     2588        InputFile >> TEFactor;
     2589        (*runner).second.second = TEFactor;
     2590        *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl;
     2591      } else {
     2592        status = false;
     2593        break;
     2594      }
     2595    }
     2596    // 4. Free and done
     2597    InputFile.close();
     2598    *out << Verbose(1) << "done." << endl;
     2599  } else {
     2600    *out << Verbose(1) << "File " << filename << " not found." << endl;
     2601    status = false;
     2602  }
     2603
     2604  // free memory
     2605  Free((void **)&filename, "molecule::ParseKeySetFile - filename");
     2606
     2607  return status;
    26082608};
    26092609
     
    26162616bool molecule::StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path)
    26172617{
    2618         ofstream output;
    2619         bool status =   true;
    2620         string line;
    2621 
    2622         // open KeySet file
    2623         line = path;
    2624         line.append("/");
    2625         line += FRAGMENTPREFIX;
    2626         line += KEYSETFILE;
    2627         output.open(line.c_str(), ios::out);
    2628         *out << Verbose(1) << "Saving key sets of the total graph ... ";
    2629         if(output != NULL) {
    2630                 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) {
    2631                         for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) {
    2632                                 if (sprinter != (*runner).first.begin())
    2633                                         output << "\t";
    2634                                 output << *sprinter;
    2635                         }
    2636                         output << endl;
    2637                 }
    2638                 *out << "done." << endl;
    2639         } else {
    2640                 cerr << "Unable to open " << line << " for writing keysets!" << endl;
    2641                 status = false;
    2642         }
    2643         output.close();
    2644         output.clear();
    2645 
    2646         // open TEFactors file
    2647         line = path;
    2648         line.append("/");
    2649         line += FRAGMENTPREFIX;
    2650         line += TEFACTORSFILE;
    2651         output.open(line.c_str(), ios::out);
    2652         *out << Verbose(1) << "Saving TEFactors of the total graph ... ";
    2653         if(output != NULL) {
    2654                 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++)
    2655                         output << (*runner).second.second << endl;
    2656                 *out << Verbose(1) << "done." << endl;
    2657         } else {
    2658                 *out << Verbose(1) << "failed to open " << line << "." << endl;
    2659                 status = false;
    2660         }
    2661         output.close();
    2662 
    2663         return status;
     2618  ofstream output;
     2619  bool status =  true;
     2620  string line;
     2621
     2622  // open KeySet file
     2623  line = path;
     2624  line.append("/");
     2625  line += FRAGMENTPREFIX;
     2626  line += KEYSETFILE;
     2627  output.open(line.c_str(), ios::out);
     2628  *out << Verbose(1) << "Saving key sets of the total graph ... ";
     2629  if(output != NULL) {
     2630    for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) {
     2631      for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) {
     2632        if (sprinter != (*runner).first.begin())
     2633          output << "\t";
     2634        output << *sprinter;
     2635      }
     2636      output << endl;
     2637    }
     2638    *out << "done." << endl;
     2639  } else {
     2640    cerr << "Unable to open " << line << " for writing keysets!" << endl;
     2641    status = false;
     2642  }
     2643  output.close();
     2644  output.clear();
     2645
     2646  // open TEFactors file
     2647  line = path;
     2648  line.append("/");
     2649  line += FRAGMENTPREFIX;
     2650  line += TEFACTORSFILE;
     2651  output.open(line.c_str(), ios::out);
     2652  *out << Verbose(1) << "Saving TEFactors of the total graph ... ";
     2653  if(output != NULL) {
     2654    for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++)
     2655      output << (*runner).second.second << endl;
     2656    *out << Verbose(1) << "done." << endl;
     2657  } else {
     2658    *out << Verbose(1) << "failed to open " << line << "." << endl;
     2659    status = false;
     2660  }
     2661  output.close();
     2662
     2663  return status;
    26642664};
    26652665
     
    26722672bool molecule::StoreAdjacencyToFile(ofstream *out, char *path)
    26732673{
    2674         ofstream AdjacencyFile;
    2675         atom *Walker = NULL;
    2676         stringstream line;
    2677         bool status = true;
    2678 
    2679         line << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;
    2680         AdjacencyFile.open(line.str().c_str(), ios::out);
    2681         *out << Verbose(1) << "Saving adjacency list ... ";
    2682         if (AdjacencyFile != NULL) {
    2683                 Walker = start;
    2684                 while(Walker->next != end) {
    2685                         Walker = Walker->next;
    2686                         AdjacencyFile << Walker->nr << "\t";
    2687                         for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++)
    2688                                 AdjacencyFile << ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker)->nr << "\t";
    2689                         AdjacencyFile << endl;
    2690                 }
    2691                 AdjacencyFile.close();
    2692                 *out << Verbose(1) << "done." << endl;
    2693         } else {
    2694                 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;
    2695                 status = false;
    2696         }
    2697 
    2698         return status;
     2674  ofstream AdjacencyFile;
     2675  atom *Walker = NULL;
     2676  stringstream line;
     2677  bool status = true;
     2678
     2679  line << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;
     2680  AdjacencyFile.open(line.str().c_str(), ios::out);
     2681  *out << Verbose(1) << "Saving adjacency list ... ";
     2682  if (AdjacencyFile != NULL) {
     2683    Walker = start;
     2684    while(Walker->next != end) {
     2685      Walker = Walker->next;
     2686      AdjacencyFile << Walker->nr << "\t";
     2687      for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++)
     2688        AdjacencyFile << ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker)->nr << "\t";
     2689      AdjacencyFile << endl;
     2690    }
     2691    AdjacencyFile.close();
     2692    *out << Verbose(1) << "done." << endl;
     2693  } else {
     2694    *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;
     2695    status = false;
     2696  }
     2697
     2698  return status;
    26992699};
    27002700
     
    27072707bool molecule::CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms)
    27082708{
    2709         ifstream File;
    2710         stringstream filename;
    2711         bool status = true;
    2712         char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");
    2713 
    2714         filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;
    2715         File.open(filename.str().c_str(), ios::out);
    2716         *out << Verbose(1) << "Looking at bond structure stored in adjacency file and comparing to present one ... ";
    2717         if (File != NULL) {
    2718                 // allocate storage structure
    2719                 int NonMatchNumber = 0; // will number of atoms with differing bond structure
    2720                 int *CurrentBonds = (int *) Malloc(sizeof(int)*8, "molecule::CheckAdjacencyFileAgainstMolecule - CurrentBonds"); // contains parsed bonds of current atom
    2721                 int CurrentBondsOfAtom;
    2722 
    2723                 // Parse the file line by line and count the bonds
    2724                 while (!File.eof()) {
    2725                         File.getline(buffer, MAXSTRINGSIZE);
    2726                         stringstream line;
    2727                         line.str(buffer);
    2728                         int AtomNr = -1;
    2729                         line >> AtomNr;
    2730                         CurrentBondsOfAtom = -1; // we count one too far due to line end
    2731                         // parse into structure
    2732                         if ((AtomNr >= 0) && (AtomNr < AtomCount)) {
    2733                                 while (!line.eof())
    2734                                         line >> CurrentBonds[ ++CurrentBondsOfAtom ];
    2735                                 // compare against present bonds
    2736                                 //cout << Verbose(2) << "Walker is " << *Walker << ", bond partners: ";
    2737                                 if (CurrentBondsOfAtom == NumberOfBondsPerAtom[AtomNr]) {
    2738                                         for(int i=0;i<NumberOfBondsPerAtom[AtomNr];i++) {
    2739                                                 int id = ListOfBondsPerAtom[AtomNr][i]->GetOtherAtom(ListOfAtoms[AtomNr])->nr;
    2740                                                 int j = 0;
    2741                                                 for (;(j<CurrentBondsOfAtom) && (CurrentBonds[j++] != id);); // check against all parsed bonds
    2742                                                 if (CurrentBonds[j-1] != id) { // no match ? Then mark in ListOfAtoms
    2743                                                         ListOfAtoms[AtomNr] = NULL;
    2744                                                         NonMatchNumber++;
    2745                                                         status = false;
    2746                                                         //out << "[" << id << "]\t";
    2747                                                 } else {
    2748                                                         //out << id << "\t";
    2749                                                 }
    2750                                         }
    2751                                         //out << endl;
    2752                                 } else {
    2753                                         *out << "Number of bonds for Atom " << *ListOfAtoms[AtomNr] << " does not match, parsed " << CurrentBondsOfAtom << " against " << NumberOfBondsPerAtom[AtomNr] << "." << endl;
    2754                                         status = false;
    2755                                 }
    2756                         }
    2757                 }
    2758                 File.close();
    2759                 File.clear();
    2760                 if (status) { // if equal we parse the KeySetFile
    2761                         *out << Verbose(1) << "done: Equal." << endl;
    2762                         status = true;
    2763                 } else
    2764                         *out << Verbose(1) << "done: Not equal by " << NonMatchNumber << " atoms." << endl;
    2765                 Free((void **)&CurrentBonds, "molecule::CheckAdjacencyFileAgainstMolecule - **CurrentBonds");
    2766         } else {
    2767                 *out << Verbose(1) << "Adjacency file not found." << endl;
    2768                 status = false;
    2769         }
    2770         *out << endl;
    2771         Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");
    2772 
    2773         return status;
     2709  ifstream File;
     2710  stringstream filename;
     2711  bool status = true;
     2712  char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");
     2713
     2714  filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;
     2715  File.open(filename.str().c_str(), ios::out);
     2716  *out << Verbose(1) << "Looking at bond structure stored in adjacency file and comparing to present one ... ";
     2717  if (File != NULL) {
     2718    // allocate storage structure
     2719    int NonMatchNumber = 0;  // will number of atoms with differing bond structure
     2720    int *CurrentBonds = (int *) Malloc(sizeof(int)*8, "molecule::CheckAdjacencyFileAgainstMolecule - CurrentBonds"); // contains parsed bonds of current atom
     2721    int CurrentBondsOfAtom;
     2722
     2723    // Parse the file line by line and count the bonds
     2724    while (!File.eof()) {
     2725      File.getline(buffer, MAXSTRINGSIZE);
     2726      stringstream line;
     2727      line.str(buffer);
     2728      int AtomNr = -1;
     2729      line >> AtomNr;
     2730      CurrentBondsOfAtom = -1; // we count one too far due to line end
     2731      // parse into structure
     2732      if ((AtomNr >= 0) && (AtomNr < AtomCount)) {
     2733        while (!line.eof())
     2734          line >> CurrentBonds[ ++CurrentBondsOfAtom ];
     2735        // compare against present bonds
     2736        //cout << Verbose(2) << "Walker is " << *Walker << ", bond partners: ";
     2737        if (CurrentBondsOfAtom == NumberOfBondsPerAtom[AtomNr]) {
     2738          for(int i=0;i<NumberOfBondsPerAtom[AtomNr];i++) {
     2739            int id = ListOfBondsPerAtom[AtomNr][i]->GetOtherAtom(ListOfAtoms[AtomNr])->nr;
     2740            int j = 0;
     2741            for (;(j<CurrentBondsOfAtom) && (CurrentBonds[j++] != id);); // check against all parsed bonds
     2742            if (CurrentBonds[j-1] != id) { // no match ? Then mark in ListOfAtoms
     2743              ListOfAtoms[AtomNr] = NULL;
     2744              NonMatchNumber++;
     2745              status = false;
     2746              //out << "[" << id << "]\t";
     2747            } else {
     2748              //out << id << "\t";
     2749            }
     2750          }
     2751          //out << endl;
     2752        } else {
     2753          *out << "Number of bonds for Atom " << *ListOfAtoms[AtomNr] << " does not match, parsed " << CurrentBondsOfAtom << " against " << NumberOfBondsPerAtom[AtomNr] << "." << endl;
     2754          status = false;
     2755        }
     2756      }
     2757    }
     2758    File.close();
     2759    File.clear();
     2760    if (status) { // if equal we parse the KeySetFile
     2761      *out << Verbose(1) << "done: Equal." << endl;
     2762      status = true;
     2763    } else
     2764      *out << Verbose(1) << "done: Not equal by " << NonMatchNumber << " atoms." << endl;
     2765    Free((void **)&CurrentBonds, "molecule::CheckAdjacencyFileAgainstMolecule - **CurrentBonds");
     2766  } else {
     2767    *out << Verbose(1) << "Adjacency file not found." << endl;
     2768    status = false;
     2769  }
     2770  *out << endl;
     2771  Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");
     2772
     2773  return status;
    27742774};
    27752775
     
    27852785bool molecule::CheckOrderAtSite(ofstream *out, bool *AtomMask, Graph *GlobalKeySetList, int Order, int *MinimumRingSize, char *path)
    27862786{
    2787         atom *Walker = start;
    2788         bool status = false;
    2789         ifstream InputFile;
    2790 
    2791         // initialize mask list
    2792         for(int i=AtomCount;i--;)
    2793                 AtomMask[i] = false;
    2794 
    2795         if (Order < 0) { // adaptive increase of BondOrder per site
    2796                 if (AtomMask[AtomCount] == true)        // break after one step
    2797                         return false;
    2798                 // parse the EnergyPerFragment file
    2799                 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckOrderAtSite: *buffer");
    2800                 sprintf(buffer, "%s/%s%s.dat", path, FRAGMENTPREFIX, ENERGYPERFRAGMENT);
    2801                 InputFile.open(buffer, ios::in);
    2802                 if ((InputFile != NULL) && (GlobalKeySetList != NULL)) {
    2803                         // transmorph graph keyset list into indexed KeySetList
    2804                         map<int,KeySet> IndexKeySetList;
    2805                         for(Graph::iterator runner = GlobalKeySetList->begin(); runner != GlobalKeySetList->end(); runner++) {
    2806                                 IndexKeySetList.insert( pair<int,KeySet>(runner->second.first,runner->first) );
    2807                         }
    2808                         int lines = 0;
    2809                         // count the number of lines, i.e. the number of fragments
    2810                         InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines
    2811                         InputFile.getline(buffer, MAXSTRINGSIZE);
    2812                         while(!InputFile.eof()) {
    2813                                 InputFile.getline(buffer, MAXSTRINGSIZE);
    2814                                 lines++;
    2815                         }
    2816                         //*out << Verbose(2) << "Scanned " << lines-1 << " lines." << endl;      // one endline too much
    2817                         InputFile.clear();
    2818                         InputFile.seekg(ios::beg);
    2819                         map<int, pair<double,int> > AdaptiveCriteriaList;       // (Root No., (Value, Order)) !
    2820                         int No, FragOrder;
    2821                         double Value;
    2822                         // each line represents a fragment root (Atom::nr) id and its energy contribution
    2823                         InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines
    2824                         InputFile.getline(buffer, MAXSTRINGSIZE);
    2825                         while(!InputFile.eof()) {
    2826                                 InputFile.getline(buffer, MAXSTRINGSIZE);
    2827                                 if (strlen(buffer) > 2) {
    2828                                         //*out << Verbose(2) << "Scanning: " << buffer << endl;
    2829                                         stringstream line(buffer);
    2830                                         line >> FragOrder;
    2831                                         line >> ws >> No;
    2832                                         line >> ws >> Value; // skip time entry
    2833                                         line >> ws >> Value;
    2834                                         No -= 1;        // indices start at 1 in file, not 0
    2835                                         //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl;
    2836 
    2837                                         // clean the list of those entries that have been superceded by higher order terms already
    2838                                         map<int,KeySet>::iterator marker = IndexKeySetList.find(No);            // find keyset to Frag No.
    2839                                         if (marker != IndexKeySetList.end()) {  // if found
    2840                                                 Value *= 1 + MYEPSILON*(*((*marker).second.begin()));            // in case of equal energies this makes em not equal without changing anything actually
    2841                                                 // as the smallest number in each set has always been the root (we use global id to keep the doubles away), seek smallest and insert into AtomMask
    2842                                                 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) ));
    2843                                                 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first;
    2844                                                 if (!InsertedElement.second) { // this root is already present
    2845                                                         if ((*PresentItem).second.second < FragOrder)   // if order there is lower, update entry with higher-order term
    2846                                                                 //if ((*PresentItem).second.first < (*runner).first)            // as higher-order terms are not always better, we skip this part (which would always include this site into adaptive increase)
    2847                                                                 {       // if value is smaller, update value and order
    2848                                                                 (*PresentItem).second.first = fabs(Value);
    2849                                                                 (*PresentItem).second.second = FragOrder;
    2850                                                                 *out << Verbose(2) << "Updated element (" <<    (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;
    2851                                                         } else {
    2852                                                                 *out << Verbose(2) << "Did not update element " <<      (*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl;
    2853                                                         }
    2854                                                 } else {
    2855                                                         *out << Verbose(2) << "Inserted element (" <<   (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;
    2856                                                 }
    2857                                         } else {
    2858                                                 *out << Verbose(1) << "No Fragment under No. " << No << "found." << endl;
    2859                                         }
    2860                                 }
    2861                         }
    2862                         // then map back onto (Value, (Root Nr., Order)) (i.e. sorted by value to pick the highest ones)
    2863                         map<double, pair<int,int> > FinalRootCandidates;
    2864                         *out << Verbose(1) << "Root candidate list is: " << endl;
    2865                         for(map<int, pair<double,int> >::iterator runner = AdaptiveCriteriaList.begin(); runner != AdaptiveCriteriaList.end(); runner++) {
    2866                                 Walker = FindAtom((*runner).first);
    2867                                 if (Walker != NULL) {
    2868                                         //if ((*runner).second.second >= Walker->AdaptiveOrder) { // only insert if this is an "active" root site for the current order
    2869                                         if (!Walker->MaxOrder) {
    2870                                                 *out << Verbose(2) << "(" << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "])" << endl;
    2871                                                 FinalRootCandidates.insert( make_pair( (*runner).second.first, pair<int,int>((*runner).first, (*runner).second.second) ) );
    2872                                         } else {
    2873                                                 *out << Verbose(2) << "Excluding (" << *Walker << ", " << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "]), as it has reached its maximum order." << endl;
    2874                                         }
    2875                                 } else {
    2876                                         cerr << "Atom No. " << (*runner).second.first << " was not found in this molecule." << endl;
    2877                                 }
    2878                         }
    2879                         // pick the ones still below threshold and mark as to be adaptively updated
    2880                         for(map<double, pair<int,int> >::iterator runner = FinalRootCandidates.upper_bound(pow(10.,Order)); runner != FinalRootCandidates.end(); runner++) {
    2881                                 No = (*runner).second.first;
    2882                                 Walker = FindAtom(No);
    2883                                 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) {
    2884                                         *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl;
    2885                                         AtomMask[No] = true;
    2886                                         status = true;
    2887                                 //} else
    2888                                         //*out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", however MinimumRingSize of " << MinimumRingSize[Walker->nr] << " does not allow further adaptive increase." << endl;
    2889                         }
    2890                         // close and done
    2891                         InputFile.close();
    2892                         InputFile.clear();
    2893                 } else {
    2894                         cerr << "Unable to parse " << buffer << " file, incrementing all." << endl;
    2895                         while (Walker->next != end) {
    2896                                 Walker = Walker->next;
    2897                 #ifdef ADDHYDROGEN
    2898                                 if (Walker->type->Z != 1) // skip hydrogen
    2899                 #endif
    2900                                 {
    2901                                         AtomMask[Walker->nr] = true;    // include all (non-hydrogen) atoms
    2902                                         status = true;
    2903                                 }
    2904                         }
    2905                 }
    2906                 Free((void **)&buffer, "molecule::CheckOrderAtSite: *buffer");
    2907                 // pick a given number of highest values and set AtomMask
    2908         } else { // global increase of Bond Order
    2909                 while (Walker->next != end) {
    2910                         Walker = Walker->next;
    2911         #ifdef ADDHYDROGEN
    2912                         if (Walker->type->Z != 1) // skip hydrogen
    2913         #endif
    2914                         {
    2915                                 AtomMask[Walker->nr] = true;    // include all (non-hydrogen) atoms
    2916                                 if ((Order != 0) && (Walker->AdaptiveOrder < Order)) // && (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]))
    2917                                         status = true;
    2918                         }
    2919                 }
    2920                 if ((Order == 0) && (AtomMask[AtomCount] == false))     // single stepping, just check
    2921                         status = true;
    2922 
    2923                 if (!status) {
    2924                         if (Order == 0)
    2925                                 *out << Verbose(1) << "Single stepping done." << endl;
    2926                         else
    2927                                 *out << Verbose(1) << "Order at every site is already equal or above desired order " << Order << "." << endl;
    2928                 }
    2929         }
    2930 
    2931         // print atom mask for debugging
    2932         *out << "                                                       ";
    2933         for(int i=0;i<AtomCount;i++)
    2934                 *out << (i % 10);
    2935         *out << endl << "Atom mask is: ";
    2936         for(int i=0;i<AtomCount;i++)
    2937                 *out << (AtomMask[i] ? "t" : "f");
    2938         *out << endl;
    2939 
    2940         return status;
     2787  atom *Walker = start;
     2788  bool status = false;
     2789  ifstream InputFile;
     2790
     2791  // initialize mask list
     2792  for(int i=AtomCount;i--;)
     2793    AtomMask[i] = false;
     2794
     2795  if (Order < 0) { // adaptive increase of BondOrder per site
     2796    if (AtomMask[AtomCount] == true)  // break after one step
     2797      return false;
     2798    // parse the EnergyPerFragment file
     2799    char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckOrderAtSite: *buffer");
     2800    sprintf(buffer, "%s/%s%s.dat", path, FRAGMENTPREFIX, ENERGYPERFRAGMENT);
     2801    InputFile.open(buffer, ios::in);
     2802    if ((InputFile != NULL) && (GlobalKeySetList != NULL)) {
     2803      // transmorph graph keyset list into indexed KeySetList
     2804      map<int,KeySet> IndexKeySetList;
     2805      for(Graph::iterator runner = GlobalKeySetList->begin(); runner != GlobalKeySetList->end(); runner++) {
     2806        IndexKeySetList.insert( pair<int,KeySet>(runner->second.first,runner->first) );
     2807      }
     2808      int lines = 0;
     2809      // count the number of lines, i.e. the number of fragments
     2810      InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines
     2811      InputFile.getline(buffer, MAXSTRINGSIZE);
     2812      while(!InputFile.eof()) {
     2813        InputFile.getline(buffer, MAXSTRINGSIZE);
     2814        lines++;
     2815      }
     2816      //*out << Verbose(2) << "Scanned " << lines-1 << " lines." << endl;  // one endline too much
     2817      InputFile.clear();
     2818      InputFile.seekg(ios::beg);
     2819      map<int, pair<double,int> > AdaptiveCriteriaList;  // (Root No., (Value, Order)) !
     2820      int No, FragOrder;
     2821      double Value;
     2822      // each line represents a fragment root (Atom::nr) id and its energy contribution
     2823      InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines
     2824      InputFile.getline(buffer, MAXSTRINGSIZE);
     2825      while(!InputFile.eof()) {
     2826        InputFile.getline(buffer, MAXSTRINGSIZE);
     2827        if (strlen(buffer) > 2) {
     2828          //*out << Verbose(2) << "Scanning: " << buffer << endl;
     2829          stringstream line(buffer);
     2830          line >> FragOrder;
     2831          line >> ws >> No;
     2832          line >> ws >> Value; // skip time entry
     2833          line >> ws >> Value;
     2834          No -= 1;  // indices start at 1 in file, not 0
     2835          //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl;
     2836
     2837          // clean the list of those entries that have been superceded by higher order terms already
     2838          map<int,KeySet>::iterator marker = IndexKeySetList.find(No);    // find keyset to Frag No.
     2839          if (marker != IndexKeySetList.end()) {  // if found
     2840            Value *= 1 + MYEPSILON*(*((*marker).second.begin()));    // in case of equal energies this makes em not equal without changing anything actually
     2841            // as the smallest number in each set has always been the root (we use global id to keep the doubles away), seek smallest and insert into AtomMask
     2842            pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) ));
     2843            map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first;
     2844            if (!InsertedElement.second) { // this root is already present
     2845              if ((*PresentItem).second.second < FragOrder)  // if order there is lower, update entry with higher-order term
     2846                //if ((*PresentItem).second.first < (*runner).first)    // as higher-order terms are not always better, we skip this part (which would always include this site into adaptive increase)
     2847                {  // if value is smaller, update value and order
     2848                (*PresentItem).second.first = fabs(Value);
     2849                (*PresentItem).second.second = FragOrder;
     2850                *out << Verbose(2) << "Updated element (" <<  (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;
     2851              } else {
     2852                *out << Verbose(2) << "Did not update element " <<  (*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl;
     2853              }
     2854            } else {
     2855              *out << Verbose(2) << "Inserted element (" <<  (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;
     2856            }
     2857          } else {
     2858            *out << Verbose(1) << "No Fragment under No. " << No << "found." << endl;
     2859          }
     2860        }
     2861      }
     2862      // then map back onto (Value, (Root Nr., Order)) (i.e. sorted by value to pick the highest ones)
     2863      map<double, pair<int,int> > FinalRootCandidates;
     2864      *out << Verbose(1) << "Root candidate list is: " << endl;
     2865      for(map<int, pair<double,int> >::iterator runner = AdaptiveCriteriaList.begin(); runner != AdaptiveCriteriaList.end(); runner++) {
     2866        Walker = FindAtom((*runner).first);
     2867        if (Walker != NULL) {
     2868          //if ((*runner).second.second >= Walker->AdaptiveOrder) { // only insert if this is an "active" root site for the current order
     2869          if (!Walker->MaxOrder) {
     2870            *out << Verbose(2) << "(" << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "])" << endl;
     2871            FinalRootCandidates.insert( make_pair( (*runner).second.first, pair<int,int>((*runner).first, (*runner).second.second) ) );
     2872          } else {
     2873            *out << Verbose(2) << "Excluding (" << *Walker << ", " << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "]), as it has reached its maximum order." << endl;
     2874          }
     2875        } else {
     2876          cerr << "Atom No. " << (*runner).second.first << " was not found in this molecule." << endl;
     2877        }
     2878      }
     2879      // pick the ones still below threshold and mark as to be adaptively updated
     2880      for(map<double, pair<int,int> >::iterator runner = FinalRootCandidates.upper_bound(pow(10.,Order)); runner != FinalRootCandidates.end(); runner++) {
     2881        No = (*runner).second.first;
     2882        Walker = FindAtom(No);
     2883        //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) {
     2884          *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl;
     2885          AtomMask[No] = true;
     2886          status = true;
     2887        //} else
     2888          //*out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", however MinimumRingSize of " << MinimumRingSize[Walker->nr] << " does not allow further adaptive increase." << endl;
     2889      }
     2890      // close and done
     2891      InputFile.close();
     2892      InputFile.clear();
     2893    } else {
     2894      cerr << "Unable to parse " << buffer << " file, incrementing all." << endl;
     2895      while (Walker->next != end) {
     2896        Walker = Walker->next;
     2897    #ifdef ADDHYDROGEN
     2898        if (Walker->type->Z != 1) // skip hydrogen
     2899    #endif
     2900        {
     2901          AtomMask[Walker->nr] = true;  // include all (non-hydrogen) atoms
     2902          status = true;
     2903        }
     2904      }
     2905    }
     2906    Free((void **)&buffer, "molecule::CheckOrderAtSite: *buffer");
     2907    // pick a given number of highest values and set AtomMask
     2908  } else { // global increase of Bond Order
     2909    while (Walker->next != end) {
     2910      Walker = Walker->next;
     2911  #ifdef ADDHYDROGEN
     2912      if (Walker->type->Z != 1) // skip hydrogen
     2913  #endif
     2914      {
     2915        AtomMask[Walker->nr] = true;  // include all (non-hydrogen) atoms
     2916        if ((Order != 0) && (Walker->AdaptiveOrder < Order)) // && (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]))
     2917          status = true;
     2918      }
     2919    }
     2920    if ((Order == 0) && (AtomMask[AtomCount] == false))  // single stepping, just check
     2921      status = true;
     2922
     2923    if (!status) {
     2924      if (Order == 0)
     2925        *out << Verbose(1) << "Single stepping done." << endl;
     2926      else
     2927        *out << Verbose(1) << "Order at every site is already equal or above desired order " << Order << "." << endl;
     2928    }
     2929  }
     2930
     2931  // print atom mask for debugging
     2932  *out << "              ";
     2933  for(int i=0;i<AtomCount;i++)
     2934    *out << (i % 10);
     2935  *out << endl << "Atom mask is: ";
     2936  for(int i=0;i<AtomCount;i++)
     2937    *out << (AtomMask[i] ? "t" : "f");
     2938  *out << endl;
     2939
     2940  return status;
    29412941};
    29422942
     
    29482948bool molecule::CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex)
    29492949{
    2950         element *runner = elemente->start;
    2951         int AtomNo = 0;
    2952         atom *Walker = NULL;
    2953 
    2954         if (SortIndex != NULL) {
    2955                 *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl;
    2956                 return false;
    2957         }
    2958         SortIndex = (int *) Malloc(sizeof(int)*AtomCount, "molecule::FragmentMolecule: *SortIndex");
    2959         for(int i=AtomCount;i--;)
    2960                 SortIndex[i] = -1;
    2961         while (runner->next != elemente->end) { // go through every element
    2962                 runner = runner->next;
    2963                 if (ElementsInMolecule[runner->Z]) { // if this element got atoms
    2964                         Walker = start;
    2965                         while (Walker->next != end) { // go through every atom of this element
    2966                                 Walker = Walker->next;
    2967                                 if (Walker->type->Z == runner->Z) // if this atom fits to element
    2968                                         SortIndex[Walker->nr] = AtomNo++;
    2969                         }
    2970                 }
    2971         }
    2972         return true;
     2950  element *runner = elemente->start;
     2951  int AtomNo = 0;
     2952  atom *Walker = NULL;
     2953
     2954  if (SortIndex != NULL) {
     2955    *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl;
     2956    return false;
     2957  }
     2958  SortIndex = (int *) Malloc(sizeof(int)*AtomCount, "molecule::FragmentMolecule: *SortIndex");
     2959  for(int i=AtomCount;i--;)
     2960    SortIndex[i] = -1;
     2961  while (runner->next != elemente->end) { // go through every element
     2962    runner = runner->next;
     2963    if (ElementsInMolecule[runner->Z]) { // if this element got atoms
     2964      Walker = start;
     2965      while (Walker->next != end) { // go through every atom of this element
     2966        Walker = Walker->next;
     2967        if (Walker->type->Z == runner->Z) // if this atom fits to element
     2968          SortIndex[Walker->nr] = AtomNo++;
     2969      }
     2970    }
     2971  }
     2972  return true;
    29732973};
    29742974
     
    29792979y contribution", and that's why this consciously not done in the following loop)
    29802980 * -# in a loop over all subgraphs
    2981  *      -# calls FragmentBOSSANOVA with this RootStack and within the subgraph molecule structure
    2982  *      -# creates molecule (fragment)s from the returned keysets (StoreFragmentFromKeySet)
     2981 *  -# calls FragmentBOSSANOVA with this RootStack and within the subgraph molecule structure
     2982 *  -# creates molecule (fragment)s from the returned keysets (StoreFragmentFromKeySet)
    29832983 * -# combines the generated molecule lists from all subgraphs
    29842984 * -# saves to disk: fragment configs, adjacency, orderatsite, keyset files
     
    29932993int molecule::FragmentMolecule(ofstream *out, int Order, config *configuration)
    29942994{
    2995         MoleculeListClass *BondFragments = NULL;
    2996         int *SortIndex = NULL;
    2997         int *MinimumRingSize = new int[AtomCount];
    2998         int FragmentCounter;
    2999         MoleculeLeafClass *MolecularWalker = NULL;
    3000         MoleculeLeafClass *Subgraphs = NULL;                    // list of subgraphs from DFS analysis
    3001         fstream File;
    3002         bool FragmentationToDo = true;
    3003         class StackClass<bond *> *BackEdgeStack = NULL, *LocalBackEdgeStack = NULL;
    3004         bool CheckOrder = false;
    3005         Graph **FragmentList = NULL;
    3006         Graph *ParsedFragmentList = NULL;
    3007         Graph TotalGraph;                // graph with all keysets however local numbers
    3008         int TotalNumberOfKeySets = 0;
    3009         atom **ListOfAtoms = NULL;
    3010         atom ***ListOfLocalAtoms = NULL;
    3011         bool *AtomMask = NULL;
    3012 
    3013         *out << endl;
     2995  MoleculeListClass *BondFragments = NULL;
     2996  int *SortIndex = NULL;
     2997  int *MinimumRingSize = new int[AtomCount];
     2998  int FragmentCounter;
     2999  MoleculeLeafClass *MolecularWalker = NULL;
     3000  MoleculeLeafClass *Subgraphs = NULL;      // list of subgraphs from DFS analysis
     3001  fstream File;
     3002  bool FragmentationToDo = true;
     3003  class StackClass<bond *> *BackEdgeStack = NULL, *LocalBackEdgeStack = NULL;
     3004  bool CheckOrder = false;
     3005  Graph **FragmentList = NULL;
     3006  Graph *ParsedFragmentList = NULL;
     3007  Graph TotalGraph;    // graph with all keysets however local numbers
     3008  int TotalNumberOfKeySets = 0;
     3009  atom **ListOfAtoms = NULL;
     3010  atom ***ListOfLocalAtoms = NULL;
     3011  bool *AtomMask = NULL;
     3012
     3013  *out << endl;
    30143014#ifdef ADDHYDROGEN
    3015         *out << Verbose(0) << "I will treat hydrogen special and saturate dangling bonds with it." << endl;
     3015  *out << Verbose(0) << "I will treat hydrogen special and saturate dangling bonds with it." << endl;
    30163016#else
    3017         *out << Verbose(0) << "Hydrogen is treated just like the rest of the lot." << endl;
     3017  *out << Verbose(0) << "Hydrogen is treated just like the rest of the lot." << endl;
    30183018#endif
    30193019
    3020         // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++
    3021 
    3022         // ===== 1. Check whether bond structure is same as stored in files ====
    3023 
    3024         // fill the adjacency list
    3025         CreateListOfBondsPerAtom(out);
    3026 
    3027         // create lookup table for Atom::nr
    3028         FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount);
    3029 
    3030         // === compare it with adjacency file ===
    3031         FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms);
    3032         Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms");
    3033 
    3034         // ===== 2. perform a DFS analysis to gather info on cyclic structure and a list of disconnected subgraphs =====
    3035         Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack);
    3036         // fill the bond structure of the individually stored subgraphs
    3037         Subgraphs->next->FillBondStructureFromReference(out, this, (FragmentCounter = 0), ListOfLocalAtoms, false);     // we want to keep the created ListOfLocalAtoms
    3038         // analysis of the cycles (print rings, get minimum cycle length) for each subgraph
    3039         for(int i=AtomCount;i--;)
    3040                 MinimumRingSize[i] = AtomCount;
    3041         MolecularWalker = Subgraphs;
    3042         FragmentCounter = 0;
    3043         while (MolecularWalker->next != NULL) {
    3044                 MolecularWalker = MolecularWalker->next;
    3045                 LocalBackEdgeStack = new StackClass<bond *> (MolecularWalker->Leaf->BondCount);
    3046 //              // check the list of local atoms for debugging
    3047 //              *out << Verbose(0) << "ListOfLocalAtoms for this subgraph is:" << endl;
    3048 //              for (int i=0;i<AtomCount;i++)
    3049 //                      if (ListOfLocalAtoms[FragmentCounter][i] == NULL)
    3050 //                              *out << "\tNULL";
    3051 //                      else
    3052 //                              *out << "\t" << ListOfLocalAtoms[FragmentCounter][i]->Name;
    3053                 *out << Verbose(0) << "Gathering local back edges for subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;
    3054                 MolecularWalker->Leaf->PickLocalBackEdges(out, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack);
    3055                 *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;
    3056                 MolecularWalker->Leaf->CyclicStructureAnalysis(out, LocalBackEdgeStack, MinimumRingSize);
    3057                 *out << Verbose(0) << "Done with Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;
    3058                 delete(LocalBackEdgeStack);
    3059         }
    3060 
    3061         // ===== 3. if structure still valid, parse key set file and others =====
    3062         FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList);
    3063 
    3064         // ===== 4. check globally whether there's something to do actually (first adaptivity check)
    3065         FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath);
    3066 
    3067         // =================================== Begin of FRAGMENTATION ===============================
    3068         // ===== 6a. assign each keyset to its respective subgraph =====
    3069         Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true);
    3070 
    3071         // ===== 6b. prepare and go into the adaptive (Order<0), single-step (Order==0) or incremental (Order>0) cycle
    3072         KeyStack *RootStack = new KeyStack[Subgraphs->next->Count()];
    3073         AtomMask = new bool[AtomCount+1];
    3074         AtomMask[AtomCount] = false;
    3075         FragmentationToDo = false;      // if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards
    3076         while ((CheckOrder = CheckOrderAtSite(out, AtomMask, ParsedFragmentList, Order, MinimumRingSize, configuration->configpath))) {
    3077                 FragmentationToDo = FragmentationToDo || CheckOrder;
    3078                 AtomMask[AtomCount] = true;      // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite()
    3079                 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) =====
    3080                 Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0));
    3081 
    3082                 // ===== 7. fill the bond fragment list =====
    3083                 FragmentCounter = 0;
    3084                 MolecularWalker = Subgraphs;
    3085                 while (MolecularWalker->next != NULL) {
    3086                         MolecularWalker = MolecularWalker->next;
    3087                         *out << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl;
    3088                         //MolecularWalker->Leaf->OutputListOfBonds(out);        // output ListOfBondsPerAtom for debugging
    3089                         if (MolecularWalker->Leaf->first->next != MolecularWalker->Leaf->last) {
    3090                                 // call BOSSANOVA method
    3091                                 *out << Verbose(0) << endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= " << endl;
    3092                                 MolecularWalker->Leaf->FragmentBOSSANOVA(out, FragmentList[FragmentCounter], RootStack[FragmentCounter], MinimumRingSize);
    3093                         } else {
    3094                                 cerr << "Subgraph " << MolecularWalker << " has no atoms!" << endl;
    3095                         }
    3096                         FragmentCounter++;      // next fragment list
    3097                 }
    3098         }
    3099         delete[](RootStack);
    3100         delete[](AtomMask);
    3101         delete(ParsedFragmentList);
    3102         delete[](MinimumRingSize);
    3103 
    3104 
    3105         // ==================================== End of FRAGMENTATION ============================================
    3106 
    3107         // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf)
    3108         Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph);
    3109 
    3110         // free subgraph memory again
    3111         FragmentCounter = 0;
    3112         if (Subgraphs != NULL) {
    3113                 while (Subgraphs->next != NULL) {
    3114                         Subgraphs = Subgraphs->next;
    3115                         delete(FragmentList[FragmentCounter++]);
    3116                         delete(Subgraphs->previous);
    3117                 }
    3118                 delete(Subgraphs);
    3119         }
    3120         Free((void **)&FragmentList, "molecule::FragmentMolecule - **FragmentList");
    3121 
    3122         // ===== 8b. gather keyset lists (graphs) from all subgraphs and transform into MoleculeListClass =====
    3123         //if (FragmentationToDo) {              // we should always store the fragments again as coordination might have changed slightly without changing bond structure
    3124                 // allocate memory for the pointer array and transmorph graphs into full molecular fragments
    3125                 BondFragments = new MoleculeListClass();
    3126                 int k=0;
    3127                 for(Graph::iterator runner = TotalGraph.begin(); runner != TotalGraph.end(); runner++) {
    3128                         KeySet test = (*runner).first;
    3129                         *out << "Fragment No." << (*runner).second.first << " with TEFactor " << (*runner).second.second << "." << endl;
    3130                         BondFragments->insert(StoreFragmentFromKeySet(out, test, configuration));
    3131                         k++;
    3132                 }
    3133                 *out << k << "/" << BondFragments->ListOfMolecules.size() << " fragments generated from the keysets." << endl;
    3134 
    3135                 // ===== 9. Save fragments' configuration and keyset files et al to disk ===
    3136                 if (BondFragments->ListOfMolecules.size() != 0) {
    3137                         // create the SortIndex from BFS labels to order in the config file
    3138                         CreateMappingLabelsToConfigSequence(out, SortIndex);
    3139 
    3140                         *out << Verbose(1) << "Writing " << BondFragments->ListOfMolecules.size() << " possible bond fragmentation configs" << endl;
    3141                         if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex))
    3142                                 *out << Verbose(1) << "All configs written." << endl;
    3143                         else
    3144                                 *out << Verbose(1) << "Some config writing failed." << endl;
    3145 
    3146                         // store force index reference file
    3147                         BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex);
    3148 
    3149                         // store keysets file
    3150                         StoreKeySetFile(out, TotalGraph, configuration->configpath);
    3151 
    3152                         // store Adjacency file
    3153                         StoreAdjacencyToFile(out, configuration->configpath);
    3154 
    3155                         // store Hydrogen saturation correction file
    3156                         BondFragments->AddHydrogenCorrection(out, configuration->configpath);
    3157 
    3158                         // store adaptive orders into file
    3159                         StoreOrderAtSiteFile(out, configuration->configpath);
    3160 
    3161                         // restore orbital and Stop values
    3162                         CalculateOrbitals(*configuration);
    3163 
    3164                         // free memory for bond part
    3165                         *out << Verbose(1) << "Freeing bond memory" << endl;
    3166                         delete(FragmentList); // remove bond molecule from memory
    3167                         Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex");
    3168                 } else
    3169                         *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl;
    3170         //} else
    3171         //      *out << Verbose(1) << "No fragments to store." << endl;
    3172         *out << Verbose(0) << "End of bond fragmentation." << endl;
    3173 
    3174         return ((int)(!FragmentationToDo)+1);           // 1 - continue, 2 - stop (no fragmentation occured)
     3020  // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++
     3021
     3022  // ===== 1. Check whether bond structure is same as stored in files ====
     3023
     3024  // fill the adjacency list
     3025  CreateListOfBondsPerAtom(out);
     3026
     3027  // create lookup table for Atom::nr
     3028  FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount);
     3029
     3030  // === compare it with adjacency file ===
     3031  FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms);
     3032  Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms");
     3033
     3034  // ===== 2. perform a DFS analysis to gather info on cyclic structure and a list of disconnected subgraphs =====
     3035  Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack);
     3036  // fill the bond structure of the individually stored subgraphs
     3037  Subgraphs->next->FillBondStructureFromReference(out, this, (FragmentCounter = 0), ListOfLocalAtoms, false);  // we want to keep the created ListOfLocalAtoms
     3038  // analysis of the cycles (print rings, get minimum cycle length) for each subgraph
     3039  for(int i=AtomCount;i--;)
     3040    MinimumRingSize[i] = AtomCount;
     3041  MolecularWalker = Subgraphs;
     3042  FragmentCounter = 0;
     3043  while (MolecularWalker->next != NULL) {
     3044    MolecularWalker = MolecularWalker->next;
     3045    LocalBackEdgeStack = new StackClass<bond *> (MolecularWalker->Leaf->BondCount);
     3046//    // check the list of local atoms for debugging
     3047//    *out << Verbose(0) << "ListOfLocalAtoms for this subgraph is:" << endl;
     3048//    for (int i=0;i<AtomCount;i++)
     3049//      if (ListOfLocalAtoms[FragmentCounter][i] == NULL)
     3050//        *out << "\tNULL";
     3051//      else
     3052//        *out << "\t" << ListOfLocalAtoms[FragmentCounter][i]->Name;
     3053    *out << Verbose(0) << "Gathering local back edges for subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;
     3054    MolecularWalker->Leaf->PickLocalBackEdges(out, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack);
     3055    *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;
     3056    MolecularWalker->Leaf->CyclicStructureAnalysis(out, LocalBackEdgeStack, MinimumRingSize);
     3057    *out << Verbose(0) << "Done with Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;
     3058    delete(LocalBackEdgeStack);
     3059  }
     3060
     3061  // ===== 3. if structure still valid, parse key set file and others =====
     3062  FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList);
     3063
     3064  // ===== 4. check globally whether there's something to do actually (first adaptivity check)
     3065  FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath);
     3066
     3067  // =================================== Begin of FRAGMENTATION ===============================
     3068  // ===== 6a. assign each keyset to its respective subgraph =====
     3069  Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true);
     3070
     3071  // ===== 6b. prepare and go into the adaptive (Order<0), single-step (Order==0) or incremental (Order>0) cycle
     3072  KeyStack *RootStack = new KeyStack[Subgraphs->next->Count()];
     3073  AtomMask = new bool[AtomCount+1];
     3074  AtomMask[AtomCount] = false;
     3075  FragmentationToDo = false;  // if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards
     3076  while ((CheckOrder = CheckOrderAtSite(out, AtomMask, ParsedFragmentList, Order, MinimumRingSize, configuration->configpath))) {
     3077    FragmentationToDo = FragmentationToDo || CheckOrder;
     3078    AtomMask[AtomCount] = true;  // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite()
     3079    // ===== 6b. fill RootStack for each subgraph (second adaptivity check) =====
     3080    Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0));
     3081
     3082    // ===== 7. fill the bond fragment list =====
     3083    FragmentCounter = 0;
     3084    MolecularWalker = Subgraphs;
     3085    while (MolecularWalker->next != NULL) {
     3086      MolecularWalker = MolecularWalker->next;
     3087      *out << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl;
     3088      //MolecularWalker->Leaf->OutputListOfBonds(out);  // output ListOfBondsPerAtom for debugging
     3089      if (MolecularWalker->Leaf->first->next != MolecularWalker->Leaf->last) {
     3090        // call BOSSANOVA method
     3091        *out << Verbose(0) << endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= " << endl;
     3092        MolecularWalker->Leaf->FragmentBOSSANOVA(out, FragmentList[FragmentCounter], RootStack[FragmentCounter], MinimumRingSize);
     3093      } else {
     3094        cerr << "Subgraph " << MolecularWalker << " has no atoms!" << endl;
     3095      }
     3096      FragmentCounter++;  // next fragment list
     3097    }
     3098  }
     3099  delete[](RootStack);
     3100  delete[](AtomMask);
     3101  delete(ParsedFragmentList);
     3102  delete[](MinimumRingSize);
     3103
     3104
     3105  // ==================================== End of FRAGMENTATION ============================================
     3106
     3107  // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf)
     3108  Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph);
     3109
     3110  // free subgraph memory again
     3111  FragmentCounter = 0;
     3112  if (Subgraphs != NULL) {
     3113    while (Subgraphs->next != NULL) {
     3114      Subgraphs = Subgraphs->next;
     3115      delete(FragmentList[FragmentCounter++]);
     3116      delete(Subgraphs->previous);
     3117    }
     3118    delete(Subgraphs);
     3119  }
     3120  Free((void **)&FragmentList, "molecule::FragmentMolecule - **FragmentList");
     3121
     3122  // ===== 8b. gather keyset lists (graphs) from all subgraphs and transform into MoleculeListClass =====
     3123  //if (FragmentationToDo) {    // we should always store the fragments again as coordination might have changed slightly without changing bond structure
     3124    // allocate memory for the pointer array and transmorph graphs into full molecular fragments
     3125    BondFragments = new MoleculeListClass();
     3126    int k=0;
     3127    for(Graph::iterator runner = TotalGraph.begin(); runner != TotalGraph.end(); runner++) {
     3128      KeySet test = (*runner).first;
     3129      *out << "Fragment No." << (*runner).second.first << " with TEFactor " << (*runner).second.second << "." << endl;
     3130      BondFragments->insert(StoreFragmentFromKeySet(out, test, configuration));
     3131      k++;
     3132    }
     3133    *out << k << "/" << BondFragments->ListOfMolecules.size() << " fragments generated from the keysets." << endl;
     3134
     3135    // ===== 9. Save fragments' configuration and keyset files et al to disk ===
     3136    if (BondFragments->ListOfMolecules.size() != 0) {
     3137      // create the SortIndex from BFS labels to order in the config file
     3138      CreateMappingLabelsToConfigSequence(out, SortIndex);
     3139
     3140      *out << Verbose(1) << "Writing " << BondFragments->ListOfMolecules.size() << " possible bond fragmentation configs" << endl;
     3141      if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex))
     3142        *out << Verbose(1) << "All configs written." << endl;
     3143      else
     3144        *out << Verbose(1) << "Some config writing failed." << endl;
     3145
     3146      // store force index reference file
     3147      BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex);
     3148
     3149      // store keysets file
     3150      StoreKeySetFile(out, TotalGraph, configuration->configpath);
     3151
     3152      // store Adjacency file
     3153      StoreAdjacencyToFile(out, configuration->configpath);
     3154
     3155      // store Hydrogen saturation correction file
     3156      BondFragments->AddHydrogenCorrection(out, configuration->configpath);
     3157
     3158      // store adaptive orders into file
     3159      StoreOrderAtSiteFile(out, configuration->configpath);
     3160
     3161      // restore orbital and Stop values
     3162      CalculateOrbitals(*configuration);
     3163
     3164      // free memory for bond part
     3165      *out << Verbose(1) << "Freeing bond memory" << endl;
     3166      delete(FragmentList); // remove bond molecule from memory
     3167      Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex");
     3168    } else
     3169      *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl;
     3170  //} else
     3171  //  *out << Verbose(1) << "No fragments to store." << endl;
     3172  *out << Verbose(0) << "End of bond fragmentation." << endl;
     3173
     3174  return ((int)(!FragmentationToDo)+1);    // 1 - continue, 2 - stop (no fragmentation occured)
    31753175};
    31763176
     
    31853185bool molecule::PickLocalBackEdges(ofstream *out, atom **ListOfLocalAtoms, class StackClass<bond *> *&ReferenceStack, class StackClass<bond *> *&LocalStack)
    31863186{
    3187         bool status = true;
    3188         if (ReferenceStack->IsEmpty()) {
    3189                 cerr << "ReferenceStack is empty!" << endl;
    3190                 return false;
    3191         }
    3192         bond *Binder = ReferenceStack->PopFirst();
    3193         bond *FirstBond = Binder;        // mark the first bond, so that we don't loop through the stack indefinitely
    3194         atom *Walker = NULL, *OtherAtom = NULL;
    3195         ReferenceStack->Push(Binder);
    3196 
    3197         do {    // go through all bonds and push local ones
    3198                 Walker = ListOfLocalAtoms[Binder->leftatom->nr];        // get one atom in the reference molecule
    3199                 if (Walker != NULL) // if this Walker exists in the subgraph ...
    3200                         for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {           // go through the local list of bonds
    3201                                 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
    3202                                 if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond
    3203                                         LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]);
    3204                                         *out << Verbose(3) << "Found local edge " << *(ListOfBondsPerAtom[Walker->nr][i]) << "." << endl;
    3205                                         break;
    3206                                 }
    3207                         }
    3208                 Binder = ReferenceStack->PopFirst();    // loop the stack for next item
    3209                 *out << Verbose(3) << "Current candidate edge " << Binder << "." << endl;
    3210                 ReferenceStack->Push(Binder);
    3211         } while (FirstBond != Binder);
    3212 
    3213         return status;
     3187  bool status = true;
     3188  if (ReferenceStack->IsEmpty()) {
     3189    cerr << "ReferenceStack is empty!" << endl;
     3190    return false;
     3191  }
     3192  bond *Binder = ReferenceStack->PopFirst();
     3193  bond *FirstBond = Binder;  // mark the first bond, so that we don't loop through the stack indefinitely
     3194  atom *Walker = NULL, *OtherAtom = NULL;
     3195  ReferenceStack->Push(Binder);
     3196
     3197  do {  // go through all bonds and push local ones
     3198    Walker = ListOfLocalAtoms[Binder->leftatom->nr];  // get one atom in the reference molecule
     3199    if (Walker != NULL) // if this Walker exists in the subgraph ...
     3200      for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {    // go through the local list of bonds
     3201        OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
     3202        if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond
     3203          LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]);
     3204          *out << Verbose(3) << "Found local edge " << *(ListOfBondsPerAtom[Walker->nr][i]) << "." << endl;
     3205          break;
     3206        }
     3207      }
     3208    Binder = ReferenceStack->PopFirst();  // loop the stack for next item
     3209    *out << Verbose(3) << "Current candidate edge " << Binder << "." << endl;
     3210    ReferenceStack->Push(Binder);
     3211  } while (FirstBond != Binder);
     3212
     3213  return status;
    32143214};
    32153215
     
    32223222bool molecule::StoreOrderAtSiteFile(ofstream *out, char *path)
    32233223{
    3224         stringstream line;
    3225         ofstream file;
    3226 
    3227         line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE;
    3228         file.open(line.str().c_str());
    3229         *out << Verbose(1) << "Writing OrderAtSite " << ORDERATSITEFILE << " ... " << endl;
    3230         if (file != NULL) {
    3231                 atom *Walker = start;
    3232                 while (Walker->next != end) {
    3233                         Walker = Walker->next;
    3234                         file << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << endl;
    3235                         *out << Verbose(2) << "Storing: " << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << "." << endl;
    3236                 }
    3237                 file.close();
    3238                 *out << Verbose(1) << "done." << endl;
    3239                 return true;
    3240         } else {
    3241                 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;
    3242                 return false;
    3243         }
     3224  stringstream line;
     3225  ofstream file;
     3226
     3227  line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE;
     3228  file.open(line.str().c_str());
     3229  *out << Verbose(1) << "Writing OrderAtSite " << ORDERATSITEFILE << " ... " << endl;
     3230  if (file != NULL) {
     3231    atom *Walker = start;
     3232    while (Walker->next != end) {
     3233      Walker = Walker->next;
     3234      file << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << endl;
     3235      *out << Verbose(2) << "Storing: " << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << "." << endl;
     3236    }
     3237    file.close();
     3238    *out << Verbose(1) << "done." << endl;
     3239    return true;
     3240  } else {
     3241    *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;
     3242    return false;
     3243  }
    32443244};
    32453245
     
    32533253bool molecule::ParseOrderAtSiteFromFile(ofstream *out, char *path)
    32543254{
    3255         unsigned char *OrderArray = (unsigned char *) Malloc(sizeof(unsigned char)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *OrderArray");
    3256         bool *MaxArray = (bool *) Malloc(sizeof(bool)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *MaxArray");
    3257         bool status;
    3258         int AtomNr, value;
    3259         stringstream line;
    3260         ifstream file;
    3261 
    3262         *out << Verbose(1) << "Begin of ParseOrderAtSiteFromFile" << endl;
    3263         for(int i=AtomCount;i--;)
    3264                 OrderArray[i] = 0;
    3265         line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE;
    3266         file.open(line.str().c_str());
    3267         if (file != NULL) {
    3268                 for (int i=AtomCount;i--;) { // initialise with 0
    3269                         OrderArray[i] = 0;
    3270                         MaxArray[i] = 0;
    3271                 }
    3272                 while (!file.eof()) { // parse from file
    3273                         AtomNr = -1;
    3274                         file >> AtomNr;
    3275                         if (AtomNr != -1) {      // test whether we really parsed something (this is necessary, otherwise last atom is set twice and to 0 on second time)
    3276                                 file >> value;
    3277                                 OrderArray[AtomNr] = value;
    3278                                 file >> value;
    3279                                 MaxArray[AtomNr] = value;
    3280                                 //*out << Verbose(2) << "AtomNr " << AtomNr << " with order " << (int)OrderArray[AtomNr] << " and max order set to " << (int)MaxArray[AtomNr] << "." << endl;
    3281                         }
    3282                 }
    3283                 atom *Walker = start;
    3284                 while (Walker->next != end) { // fill into atom classes
    3285                         Walker = Walker->next;
    3286                         Walker->AdaptiveOrder = OrderArray[Walker->nr];
    3287                         Walker->MaxOrder = MaxArray[Walker->nr];
    3288                         *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl;
    3289                 }
    3290                 file.close();
    3291                 *out << Verbose(1) << "done." << endl;
    3292                 status = true;
    3293         } else {
    3294                 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;
    3295                 status = false;
    3296         }
    3297         Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray");
    3298         Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray");
    3299 
    3300         *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl;
    3301         return status;
     3255  unsigned char *OrderArray = (unsigned char *) Malloc(sizeof(unsigned char)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *OrderArray");
     3256  bool *MaxArray = (bool *) Malloc(sizeof(bool)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *MaxArray");
     3257  bool status;
     3258  int AtomNr, value;
     3259  stringstream line;
     3260  ifstream file;
     3261
     3262  *out << Verbose(1) << "Begin of ParseOrderAtSiteFromFile" << endl;
     3263  for(int i=AtomCount;i--;)
     3264    OrderArray[i] = 0;
     3265  line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE;
     3266  file.open(line.str().c_str());
     3267  if (file != NULL) {
     3268    for (int i=AtomCount;i--;) { // initialise with 0
     3269      OrderArray[i] = 0;
     3270      MaxArray[i] = 0;
     3271    }
     3272    while (!file.eof()) { // parse from file
     3273      AtomNr = -1;
     3274      file >> AtomNr;
     3275      if (AtomNr != -1) {  // test whether we really parsed something (this is necessary, otherwise last atom is set twice and to 0 on second time)
     3276        file >> value;
     3277        OrderArray[AtomNr] = value;
     3278        file >> value;
     3279        MaxArray[AtomNr] = value;
     3280        //*out << Verbose(2) << "AtomNr " << AtomNr << " with order " << (int)OrderArray[AtomNr] << " and max order set to " << (int)MaxArray[AtomNr] << "." << endl;
     3281      }
     3282    }
     3283    atom *Walker = start;
     3284    while (Walker->next != end) { // fill into atom classes
     3285      Walker = Walker->next;
     3286      Walker->AdaptiveOrder = OrderArray[Walker->nr];
     3287      Walker->MaxOrder = MaxArray[Walker->nr];
     3288      *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl;
     3289    }
     3290    file.close();
     3291    *out << Verbose(1) << "done." << endl;
     3292    status = true;
     3293  } else {
     3294    *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;
     3295    status = false;
     3296  }
     3297  Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray");
     3298  Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray");
     3299
     3300  *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl;
     3301  return status;
    33023302};
    33033303
     
    33103310void molecule::CreateListOfBondsPerAtom(ofstream *out)
    33113311{
    3312         bond *Binder = NULL;
    3313         atom *Walker = NULL;
    3314         int TotalDegree;
    3315         *out << Verbose(1) << "Begin of Creating ListOfBondsPerAtom: AtomCount = " << AtomCount << "\tBondCount = " << BondCount << "\tNoNonBonds = " << NoNonBonds << "." << endl;
    3316 
    3317         // re-allocate memory
    3318         *out << Verbose(2) << "(Re-)Allocating memory." << endl;
    3319         if (ListOfBondsPerAtom != NULL) {
    3320                 for(int i=AtomCount;i--;)
    3321                         Free((void **)&ListOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom[i]");
    3322                 Free((void **)&ListOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom");
    3323         }
    3324         if (NumberOfBondsPerAtom != NULL)
    3325                 Free((void **)&NumberOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: NumberOfBondsPerAtom");
    3326         ListOfBondsPerAtom = (bond ***) Malloc(sizeof(bond **)*AtomCount, "molecule::CreateListOfBondsPerAtom: ***ListOfBondsPerAtom");
    3327         NumberOfBondsPerAtom = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfBondsPerAtom: *NumberOfBondsPerAtom");
    3328 
    3329         // reset bond counts per atom
    3330         for(int i=AtomCount;i--;)
    3331                 NumberOfBondsPerAtom[i] = 0;
    3332         // count bonds per atom
    3333         Binder = first;
    3334         while (Binder->next != last) {
    3335                 Binder = Binder->next;
    3336                 NumberOfBondsPerAtom[Binder->leftatom->nr]++;
    3337                 NumberOfBondsPerAtom[Binder->rightatom->nr]++;
    3338         }
    3339         for(int i=AtomCount;i--;) {
    3340                 // allocate list of bonds per atom
    3341                 ListOfBondsPerAtom[i] = (bond **) Malloc(sizeof(bond *)*NumberOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: **ListOfBondsPerAtom[]");
    3342                 // clear the list again, now each NumberOfBondsPerAtom marks current free field
    3343                 NumberOfBondsPerAtom[i] = 0;
    3344         }
    3345         // fill the list
    3346         Binder = first;
    3347         while (Binder->next != last) {
    3348                 Binder = Binder->next;
    3349                 ListOfBondsPerAtom[Binder->leftatom->nr][NumberOfBondsPerAtom[Binder->leftatom->nr]++] = Binder;
    3350                 ListOfBondsPerAtom[Binder->rightatom->nr][NumberOfBondsPerAtom[Binder->rightatom->nr]++] = Binder;
    3351         }
    3352 
    3353         // output list for debugging
    3354         *out << Verbose(3) << "ListOfBondsPerAtom for each atom:" << endl;
    3355         Walker = start;
    3356         while (Walker->next != end) {
    3357                 Walker = Walker->next;
    3358                 *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: ";
    3359                 TotalDegree = 0;
    3360                 for (int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) {
    3361                         *out << *ListOfBondsPerAtom[Walker->nr][j] << "\t";
    3362                         TotalDegree += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;
    3363                 }
    3364                 *out << " -- TotalDegree: " << TotalDegree << endl;
    3365         }
    3366         *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl;
     3312  bond *Binder = NULL;
     3313  atom *Walker = NULL;
     3314  int TotalDegree;
     3315  *out << Verbose(1) << "Begin of Creating ListOfBondsPerAtom: AtomCount = " << AtomCount << "\tBondCount = " << BondCount << "\tNoNonBonds = " << NoNonBonds << "." << endl;
     3316
     3317  // re-allocate memory
     3318  *out << Verbose(2) << "(Re-)Allocating memory." << endl;
     3319  if (ListOfBondsPerAtom != NULL) {
     3320    for(int i=AtomCount;i--;)
     3321      Free((void **)&ListOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom[i]");
     3322    Free((void **)&ListOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom");
     3323  }
     3324  if (NumberOfBondsPerAtom != NULL)
     3325    Free((void **)&NumberOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: NumberOfBondsPerAtom");
     3326  ListOfBondsPerAtom = (bond ***) Malloc(sizeof(bond **)*AtomCount, "molecule::CreateListOfBondsPerAtom: ***ListOfBondsPerAtom");
     3327  NumberOfBondsPerAtom = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfBondsPerAtom: *NumberOfBondsPerAtom");
     3328
     3329  // reset bond counts per atom
     3330  for(int i=AtomCount;i--;)
     3331    NumberOfBondsPerAtom[i] = 0;
     3332  // count bonds per atom
     3333  Binder = first;
     3334  while (Binder->next != last) {
     3335    Binder = Binder->next;
     3336    NumberOfBondsPerAtom[Binder->leftatom->nr]++;
     3337    NumberOfBondsPerAtom[Binder->rightatom->nr]++;
     3338  }
     3339  for(int i=AtomCount;i--;) {
     3340    // allocate list of bonds per atom
     3341    ListOfBondsPerAtom[i] = (bond **) Malloc(sizeof(bond *)*NumberOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: **ListOfBondsPerAtom[]");
     3342    // clear the list again, now each NumberOfBondsPerAtom marks current free field
     3343    NumberOfBondsPerAtom[i] = 0;
     3344  }
     3345  // fill the list
     3346  Binder = first;
     3347  while (Binder->next != last) {
     3348    Binder = Binder->next;
     3349    ListOfBondsPerAtom[Binder->leftatom->nr][NumberOfBondsPerAtom[Binder->leftatom->nr]++] = Binder;
     3350    ListOfBondsPerAtom[Binder->rightatom->nr][NumberOfBondsPerAtom[Binder->rightatom->nr]++] = Binder;
     3351  }
     3352
     3353  // output list for debugging
     3354  *out << Verbose(3) << "ListOfBondsPerAtom for each atom:" << endl;
     3355  Walker = start;
     3356  while (Walker->next != end) {
     3357    Walker = Walker->next;
     3358    *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: ";
     3359    TotalDegree = 0;
     3360    for (int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) {
     3361      *out << *ListOfBondsPerAtom[Walker->nr][j] << "\t";
     3362      TotalDegree += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;
     3363    }
     3364    *out << " -- TotalDegree: " << TotalDegree << endl;
     3365  }
     3366  *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl;
    33673367};
    33683368
     
    33813381void molecule::BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem)
    33823382{
    3383         atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::BreadthFirstSearchAdd: **PredecessorList");
    3384         int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::BreadthFirstSearchAdd: *ShortestPathList");
    3385         enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::BreadthFirstSearchAdd: *ColorList");
    3386         class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);
    3387         atom *Walker = NULL, *OtherAtom = NULL;
    3388         bond *Binder = NULL;
    3389 
    3390         // add Root if not done yet
    3391         AtomStack->ClearStack();
    3392         if (AddedAtomList[Root->nr] == NULL)    // add Root if not yet present
    3393                 AddedAtomList[Root->nr] = Mol->AddCopyAtom(Root);
    3394         AtomStack->Push(Root);
    3395 
    3396         // initialise each vertex as white with no predecessor, empty queue, color Root lightgray
    3397         for (int i=AtomCount;i--;) {
    3398                 PredecessorList[i] = NULL;
    3399                 ShortestPathList[i] = -1;
    3400                 if (AddedAtomList[i] != NULL) // mark already present atoms (i.e. Root and maybe others) as visited
    3401                         ColorList[i] = lightgray;
    3402                 else
    3403                         ColorList[i] = white;
    3404         }
    3405         ShortestPathList[Root->nr] = 0;
    3406 
    3407         // and go on ... Queue always contains all lightgray vertices
    3408         while (!AtomStack->IsEmpty()) {
    3409                 // we have to pop the oldest atom from stack. This keeps the atoms on the stack always of the same ShortestPath distance.
    3410                 // e.g. if current atom is 2, push to end of stack are of length 3, but first all of length 2 would be popped. They again
    3411                 // append length of 3 (their neighbours). Thus on stack we have always atoms of a certain length n at bottom of stack and
    3412                 // followed by n+1 till top of stack.
    3413                 Walker = AtomStack->PopFirst(); // pop oldest added
    3414                 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl;
    3415                 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
    3416                         Binder = ListOfBondsPerAtom[Walker->nr][i];
    3417                         if (Binder != NULL) { // don't look at bond equal NULL
    3418                                 OtherAtom = Binder->GetOtherAtom(Walker);
    3419                                 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
    3420                                 if (ColorList[OtherAtom->nr] == white) {
    3421                                         if (Binder != Bond) // let other atom white if it's via Root bond. In case it's cyclic it has to be reached again (yet Root is from OtherAtom already black, thus no problem)
    3422                                                 ColorList[OtherAtom->nr] = lightgray;
    3423                                         PredecessorList[OtherAtom->nr] = Walker;        // Walker is the predecessor
    3424                                         ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
    3425                                         *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " " << ((ColorList[OtherAtom->nr] == white) ? "white" : "lightgray") << ", its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl;
    3426                                         if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance
    3427                                                 *out << Verbose(3);
    3428                                                 if (AddedAtomList[OtherAtom->nr] == NULL) { // add if it's not been so far
    3429                                                         AddedAtomList[OtherAtom->nr] = Mol->AddCopyAtom(OtherAtom);
    3430                                                         *out << "Added OtherAtom " << OtherAtom->Name;
    3431                                                         AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
    3432                                                         AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
    3433                                                         AddedBondList[Binder->nr]->Type = Binder->Type;
    3434                                                         *out << " and bond " << *(AddedBondList[Binder->nr]) << ", ";
    3435                                                 } else {        // this code should actually never come into play (all white atoms are not yet present in BondMolecule, that's why they are white in the first place)
    3436                                                         *out << "Not adding OtherAtom " << OtherAtom->Name;
    3437                                                         if (AddedBondList[Binder->nr] == NULL) {
    3438                                                                 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
    3439                                                                 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
    3440                                                                 AddedBondList[Binder->nr]->Type = Binder->Type;
    3441                                                                 *out << ", added Bond " << *(AddedBondList[Binder->nr]);
    3442                                                         } else
    3443                                                                 *out << ", not added Bond ";
    3444                                                 }
    3445                                                 *out << ", putting OtherAtom into queue." << endl;
    3446                                                 AtomStack->Push(OtherAtom);
    3447                                         } else { // out of bond order, then replace
    3448                                                 if ((AddedAtomList[OtherAtom->nr] == NULL) && (Binder->Cyclic))
    3449                                                         ColorList[OtherAtom->nr] = white; // unmark if it has not been queued/added, to make it available via its other bonds (cyclic)
    3450                                                 if (Binder == Bond)
    3451                                                         *out << Verbose(3) << "Not Queueing, is the Root bond";
    3452                                                 else if (ShortestPathList[OtherAtom->nr] >= BondOrder)
    3453                                                         *out << Verbose(3) << "Not Queueing, is out of Bond Count of " << BondOrder;
    3454                                                 if (!Binder->Cyclic)
    3455                                                         *out << ", is not part of a cyclic bond, saturating bond with Hydrogen." << endl;
    3456                                                 if (AddedBondList[Binder->nr] == NULL) {
    3457                                                         if ((AddedAtomList[OtherAtom->nr] != NULL)) { // .. whether we add or saturate
    3458                                                                 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
    3459                                                                 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
    3460                                                                 AddedBondList[Binder->nr]->Type = Binder->Type;
    3461                                                         } else {
     3383  atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::BreadthFirstSearchAdd: **PredecessorList");
     3384  int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::BreadthFirstSearchAdd: *ShortestPathList");
     3385  enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::BreadthFirstSearchAdd: *ColorList");
     3386  class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);
     3387  atom *Walker = NULL, *OtherAtom = NULL;
     3388  bond *Binder = NULL;
     3389
     3390  // add Root if not done yet
     3391  AtomStack->ClearStack();
     3392  if (AddedAtomList[Root->nr] == NULL)  // add Root if not yet present
     3393    AddedAtomList[Root->nr] = Mol->AddCopyAtom(Root);
     3394  AtomStack->Push(Root);
     3395
     3396  // initialise each vertex as white with no predecessor, empty queue, color Root lightgray
     3397  for (int i=AtomCount;i--;) {
     3398    PredecessorList[i] = NULL;
     3399    ShortestPathList[i] = -1;
     3400    if (AddedAtomList[i] != NULL) // mark already present atoms (i.e. Root and maybe others) as visited
     3401      ColorList[i] = lightgray;
     3402    else
     3403      ColorList[i] = white;
     3404  }
     3405  ShortestPathList[Root->nr] = 0;
     3406
     3407  // and go on ... Queue always contains all lightgray vertices
     3408  while (!AtomStack->IsEmpty()) {
     3409    // we have to pop the oldest atom from stack. This keeps the atoms on the stack always of the same ShortestPath distance.
     3410    // e.g. if current atom is 2, push to end of stack are of length 3, but first all of length 2 would be popped. They again
     3411    // append length of 3 (their neighbours). Thus on stack we have always atoms of a certain length n at bottom of stack and
     3412    // followed by n+1 till top of stack.
     3413    Walker = AtomStack->PopFirst(); // pop oldest added
     3414    *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl;
     3415    for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
     3416      Binder = ListOfBondsPerAtom[Walker->nr][i];
     3417      if (Binder != NULL) { // don't look at bond equal NULL
     3418        OtherAtom = Binder->GetOtherAtom(Walker);
     3419        *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
     3420        if (ColorList[OtherAtom->nr] == white) {
     3421          if (Binder != Bond) // let other atom white if it's via Root bond. In case it's cyclic it has to be reached again (yet Root is from OtherAtom already black, thus no problem)
     3422            ColorList[OtherAtom->nr] = lightgray;
     3423          PredecessorList[OtherAtom->nr] = Walker;  // Walker is the predecessor
     3424          ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
     3425          *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " " << ((ColorList[OtherAtom->nr] == white) ? "white" : "lightgray") << ", its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl;
     3426          if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance
     3427            *out << Verbose(3);
     3428            if (AddedAtomList[OtherAtom->nr] == NULL) { // add if it's not been so far
     3429              AddedAtomList[OtherAtom->nr] = Mol->AddCopyAtom(OtherAtom);
     3430              *out << "Added OtherAtom " << OtherAtom->Name;
     3431              AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
     3432              AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
     3433              AddedBondList[Binder->nr]->Type = Binder->Type;
     3434              *out << " and bond " << *(AddedBondList[Binder->nr]) << ", ";
     3435            } else {  // this code should actually never come into play (all white atoms are not yet present in BondMolecule, that's why they are white in the first place)
     3436              *out << "Not adding OtherAtom " << OtherAtom->Name;
     3437              if (AddedBondList[Binder->nr] == NULL) {
     3438                AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
     3439                AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
     3440                AddedBondList[Binder->nr]->Type = Binder->Type;
     3441                *out << ", added Bond " << *(AddedBondList[Binder->nr]);
     3442              } else
     3443                *out << ", not added Bond ";
     3444            }
     3445            *out << ", putting OtherAtom into queue." << endl;
     3446            AtomStack->Push(OtherAtom);
     3447          } else { // out of bond order, then replace
     3448            if ((AddedAtomList[OtherAtom->nr] == NULL) && (Binder->Cyclic))
     3449              ColorList[OtherAtom->nr] = white; // unmark if it has not been queued/added, to make it available via its other bonds (cyclic)
     3450            if (Binder == Bond)
     3451              *out << Verbose(3) << "Not Queueing, is the Root bond";
     3452            else if (ShortestPathList[OtherAtom->nr] >= BondOrder)
     3453              *out << Verbose(3) << "Not Queueing, is out of Bond Count of " << BondOrder;
     3454            if (!Binder->Cyclic)
     3455              *out << ", is not part of a cyclic bond, saturating bond with Hydrogen." << endl;
     3456            if (AddedBondList[Binder->nr] == NULL) {
     3457              if ((AddedAtomList[OtherAtom->nr] != NULL)) { // .. whether we add or saturate
     3458                AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
     3459                AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
     3460                AddedBondList[Binder->nr]->Type = Binder->Type;
     3461              } else {
    34623462#ifdef ADDHYDROGEN
    3463                                                                 if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))
    3464                                                                         exit(1);
     3463                if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))
     3464                  exit(1);
    34653465#endif
    3466                                                         }
    3467                                                 }
    3468                                         }
    3469                                 } else {
    3470                                         *out << Verbose(3) << "Not Adding, has already been visited." << endl;
    3471                                         // This has to be a cyclic bond, check whether it's present ...
    3472                                         if (AddedBondList[Binder->nr] == NULL) {
    3473                                                 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) {
    3474                                                         AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
    3475                                                         AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
    3476                                                         AddedBondList[Binder->nr]->Type = Binder->Type;
    3477                                                 } else { // if it's root bond it has to broken (otherwise we would not create the fragments)
     3466              }
     3467            }
     3468          }
     3469        } else {
     3470          *out << Verbose(3) << "Not Adding, has already been visited." << endl;
     3471          // This has to be a cyclic bond, check whether it's present ...
     3472          if (AddedBondList[Binder->nr] == NULL) {
     3473            if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) {
     3474              AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
     3475              AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
     3476              AddedBondList[Binder->nr]->Type = Binder->Type;
     3477            } else { // if it's root bond it has to broken (otherwise we would not create the fragments)
    34783478#ifdef ADDHYDROGEN
    3479                                                         if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))
    3480                                                                 exit(1);
     3479              if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))
     3480                exit(1);
    34813481#endif
    3482                                                 }
    3483                                         }
    3484                                 }
    3485                         }
    3486                 }
    3487                 ColorList[Walker->nr] = black;
    3488                 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
    3489         }
    3490         Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList");
    3491         Free((void **)&ShortestPathList, "molecule::BreadthFirstSearchAdd: **ShortestPathList");
    3492         Free((void **)&ColorList, "molecule::BreadthFirstSearchAdd: **ColorList");
    3493         delete(AtomStack);
     3482            }
     3483          }
     3484        }
     3485      }
     3486    }
     3487    ColorList[Walker->nr] = black;
     3488    *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
     3489  }
     3490  Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList");
     3491  Free((void **)&ShortestPathList, "molecule::BreadthFirstSearchAdd: **ShortestPathList");
     3492  Free((void **)&ColorList, "molecule::BreadthFirstSearchAdd: **ColorList");
     3493  delete(AtomStack);
    34943494};
    34953495
     
    35053505bool molecule::BuildInducedSubgraph(ofstream *out, const molecule *Father)
    35063506{
    3507         atom *Walker = NULL, *OtherAtom = NULL;
    3508         bool status = true;
    3509         atom **ParentList = (atom **) Malloc(sizeof(atom *)*Father->AtomCount, "molecule::BuildInducedSubgraph: **ParentList");
    3510 
    3511         *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl;
    3512 
    3513         // reset parent list
    3514         *out << Verbose(3) << "Resetting ParentList." << endl;
    3515         for (int i=Father->AtomCount;i--;)
    3516                 ParentList[i] = NULL;
    3517 
    3518         // fill parent list with sons
    3519         *out << Verbose(3) << "Filling Parent List." << endl;
    3520         Walker = start;
    3521         while (Walker->next != end) {
    3522                 Walker = Walker->next;
    3523                 ParentList[Walker->father->nr] = Walker;
    3524                 // Outputting List for debugging
    3525                 *out << Verbose(4) << "Son["<< Walker->father->nr <<"] of " << Walker->father <<        " is " << ParentList[Walker->father->nr] << "." << endl;
    3526         }
    3527 
    3528         // check each entry of parent list and if ok (one-to-and-onto matching) create bonds
    3529         *out << Verbose(3) << "Creating bonds." << endl;
    3530         Walker = Father->start;
    3531         while (Walker->next != Father->end) {
    3532                 Walker = Walker->next;
    3533                 if (ParentList[Walker->nr] != NULL) {
    3534                         if (ParentList[Walker->nr]->father != Walker) {
    3535                                 status = false;
    3536                         } else {
    3537                                 for (int i=0;i<Father->NumberOfBondsPerAtom[Walker->nr];i++) {
    3538                                         OtherAtom = Father->ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
    3539                                         if (ParentList[OtherAtom->nr] != NULL) { // if otheratom is also a father of an atom on this molecule, create the bond
    3540                                                 *out << Verbose(4) << "Endpoints of Bond " << Father->ListOfBondsPerAtom[Walker->nr][i] << " are both present: " << ParentList[Walker->nr]->Name << " and " << ParentList[OtherAtom->nr]->Name << "." << endl;
    3541                                                 AddBond(ParentList[Walker->nr], ParentList[OtherAtom->nr], Father->ListOfBondsPerAtom[Walker->nr][i]->BondDegree);
    3542                                         }
    3543                                 }
    3544                         }
    3545                 }
    3546         }
    3547 
    3548         Free((void **)&ParentList, "molecule::BuildInducedSubgraph: **ParentList");
    3549         *out << Verbose(2) << "End of BuildInducedSubgraph." << endl;
    3550         return status;
     3507  atom *Walker = NULL, *OtherAtom = NULL;
     3508  bool status = true;
     3509  atom **ParentList = (atom **) Malloc(sizeof(atom *)*Father->AtomCount, "molecule::BuildInducedSubgraph: **ParentList");
     3510
     3511  *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl;
     3512
     3513  // reset parent list
     3514  *out << Verbose(3) << "Resetting ParentList." << endl;
     3515  for (int i=Father->AtomCount;i--;)
     3516    ParentList[i] = NULL;
     3517
     3518  // fill parent list with sons
     3519  *out << Verbose(3) << "Filling Parent List." << endl;
     3520  Walker = start;
     3521  while (Walker->next != end) {
     3522    Walker = Walker->next;
     3523    ParentList[Walker->father->nr] = Walker;
     3524    // Outputting List for debugging
     3525    *out << Verbose(4) << "Son["<< Walker->father->nr <<"] of " << Walker->father <<  " is " << ParentList[Walker->father->nr] << "." << endl;
     3526  }
     3527
     3528  // check each entry of parent list and if ok (one-to-and-onto matching) create bonds
     3529  *out << Verbose(3) << "Creating bonds." << endl;
     3530  Walker = Father->start;
     3531  while (Walker->next != Father->end) {
     3532    Walker = Walker->next;
     3533    if (ParentList[Walker->nr] != NULL) {
     3534      if (ParentList[Walker->nr]->father != Walker) {
     3535        status = false;
     3536      } else {
     3537        for (int i=0;i<Father->NumberOfBondsPerAtom[Walker->nr];i++) {
     3538          OtherAtom = Father->ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
     3539          if (ParentList[OtherAtom->nr] != NULL) { // if otheratom is also a father of an atom on this molecule, create the bond
     3540            *out << Verbose(4) << "Endpoints of Bond " << Father->ListOfBondsPerAtom[Walker->nr][i] << " are both present: " << ParentList[Walker->nr]->Name << " and " << ParentList[OtherAtom->nr]->Name << "." << endl;
     3541            AddBond(ParentList[Walker->nr], ParentList[OtherAtom->nr], Father->ListOfBondsPerAtom[Walker->nr][i]->BondDegree);
     3542          }
     3543        }
     3544      }
     3545    }
     3546  }
     3547
     3548  Free((void **)&ParentList, "molecule::BuildInducedSubgraph: **ParentList");
     3549  *out << Verbose(2) << "End of BuildInducedSubgraph." << endl;
     3550  return status;
    35513551};
    35523552
     
    35603560int molecule::LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList)
    35613561{
    3562         atom *Runner = NULL;
    3563         int SP, Removal;
    3564 
    3565         *out << Verbose(2) << "Looking for removal candidate." << endl;
    3566         SP = -1; //0;   // not -1, so that Root is never removed
    3567         Removal = -1;
    3568         for (KeySet::iterator runner = Leaf->begin(); runner != Leaf->end(); runner++) {
    3569                 Runner = FindAtom((*runner));
    3570                 if (Runner->type->Z != 1) { // skip all those added hydrogens when re-filling snake stack
    3571                         if (ShortestPathList[(*runner)] > SP) { // remove the oldest one with longest shortest path
    3572                                 SP = ShortestPathList[(*runner)];
    3573                                 Removal = (*runner);
    3574                         }
    3575                 }
    3576         }
    3577         return Removal;
     3562  atom *Runner = NULL;
     3563  int SP, Removal;
     3564
     3565  *out << Verbose(2) << "Looking for removal candidate." << endl;
     3566  SP = -1; //0;  // not -1, so that Root is never removed
     3567  Removal = -1;
     3568  for (KeySet::iterator runner = Leaf->begin(); runner != Leaf->end(); runner++) {
     3569    Runner = FindAtom((*runner));
     3570    if (Runner->type->Z != 1) { // skip all those added hydrogens when re-filling snake stack
     3571      if (ShortestPathList[(*runner)] > SP) {  // remove the oldest one with longest shortest path
     3572        SP = ShortestPathList[(*runner)];
     3573        Removal = (*runner);
     3574      }
     3575    }
     3576  }
     3577  return Removal;
    35783578};
    35793579
     
    35883588molecule * molecule::StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem)
    35893589{
    3590         atom *Runner = NULL, *FatherOfRunner = NULL, *OtherFather = NULL;
    3591         atom **SonList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::StoreFragmentFromStack: **SonList");
    3592         molecule *Leaf = new molecule(elemente);
    3593         bool LonelyFlag = false;
    3594         int size;
    3595 
    3596 //      *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl;
    3597 
    3598         Leaf->BondDistance = BondDistance;
    3599         for(int i=NDIM*2;i--;)
    3600                 Leaf->cell_size[i] = cell_size[i];
    3601 
    3602         // initialise SonList (indicates when we need to replace a bond with hydrogen instead)
    3603         for(int i=AtomCount;i--;)
    3604                 SonList[i] = NULL;
    3605 
    3606         // first create the minimal set of atoms from the KeySet
    3607         size = 0;
    3608         for(KeySet::iterator runner = Leaflet.begin(); runner != Leaflet.end(); runner++) {
    3609                 FatherOfRunner = FindAtom((*runner));   // find the id
    3610                 SonList[FatherOfRunner->nr] = Leaf->AddCopyAtom(FatherOfRunner);
    3611                 size++;
    3612         }
    3613 
    3614         // create the bonds between all: Make it an induced subgraph and add hydrogen
    3615 //      *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl;
    3616         Runner = Leaf->start;
    3617         while (Runner->next != Leaf->end) {
    3618                 Runner = Runner->next;
    3619                 LonelyFlag = true;
    3620                 FatherOfRunner = Runner->father;
    3621                 if (SonList[FatherOfRunner->nr] != NULL)        {       // check if this, our father, is present in list
    3622                         // create all bonds
    3623                         for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father
    3624                                 OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner);
    3625 //                              *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather;
    3626                                 if (SonList[OtherFather->nr] != NULL) {
    3627 //                                      *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl;
    3628                                         if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba)
    3629 //                                              *out << Verbose(3) << "Adding Bond: ";
    3630 //                                              *out <<
    3631                                                 Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree);
    3632 //                                              *out << "." << endl;
    3633                                                 //NumBonds[Runner->nr]++;
    3634                                         } else {
    3635 //                                              *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl;
    3636                                         }
    3637                                         LonelyFlag = false;
    3638                                 } else {
    3639 //                                      *out << ", who has no son in this fragment molecule." << endl;
     3590  atom *Runner = NULL, *FatherOfRunner = NULL, *OtherFather = NULL;
     3591  atom **SonList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::StoreFragmentFromStack: **SonList");
     3592  molecule *Leaf = new molecule(elemente);
     3593  bool LonelyFlag = false;
     3594  int size;
     3595
     3596//  *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl;
     3597
     3598  Leaf->BondDistance = BondDistance;
     3599  for(int i=NDIM*2;i--;)
     3600    Leaf->cell_size[i] = cell_size[i];
     3601
     3602  // initialise SonList (indicates when we need to replace a bond with hydrogen instead)
     3603  for(int i=AtomCount;i--;)
     3604    SonList[i] = NULL;
     3605
     3606  // first create the minimal set of atoms from the KeySet
     3607  size = 0;
     3608  for(KeySet::iterator runner = Leaflet.begin(); runner != Leaflet.end(); runner++) {
     3609    FatherOfRunner = FindAtom((*runner));  // find the id
     3610    SonList[FatherOfRunner->nr] = Leaf->AddCopyAtom(FatherOfRunner);
     3611    size++;
     3612  }
     3613
     3614  // create the bonds between all: Make it an induced subgraph and add hydrogen
     3615//  *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl;
     3616  Runner = Leaf->start;
     3617  while (Runner->next != Leaf->end) {
     3618    Runner = Runner->next;
     3619    LonelyFlag = true;
     3620    FatherOfRunner = Runner->father;
     3621    if (SonList[FatherOfRunner->nr] != NULL)  {  // check if this, our father, is present in list
     3622      // create all bonds
     3623      for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father
     3624        OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner);
     3625//        *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather;
     3626        if (SonList[OtherFather->nr] != NULL) {
     3627//          *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl;
     3628          if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba)
     3629//            *out << Verbose(3) << "Adding Bond: ";
     3630//            *out <<
     3631            Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree);
     3632//            *out << "." << endl;
     3633            //NumBonds[Runner->nr]++;
     3634          } else {
     3635//            *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl;
     3636          }
     3637          LonelyFlag = false;
     3638        } else {
     3639//          *out << ", who has no son in this fragment molecule." << endl;
    36403640#ifdef ADDHYDROGEN
    3641                                         //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl;
    3642                                         if(!Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem))
    3643                                                 exit(1);
     3641          //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl;
     3642          if(!Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem))
     3643            exit(1);
    36443644#endif
    3645                                         //NumBonds[Runner->nr] += ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree;
    3646                                 }
    3647                         }
    3648                 } else {
    3649                         *out << Verbose(0) << "ERROR: Son " << Runner->Name << " has father " << FatherOfRunner->Name << " but its entry in SonList is " << SonList[FatherOfRunner->nr] << "!" << endl;
    3650                 }
    3651                 if ((LonelyFlag) && (size > 1)) {
    3652                         *out << Verbose(0) << *Runner << "has got bonds only to hydrogens!" << endl;
    3653                 }
     3645          //NumBonds[Runner->nr] += ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree;
     3646        }
     3647      }
     3648    } else {
     3649      *out << Verbose(0) << "ERROR: Son " << Runner->Name << " has father " << FatherOfRunner->Name << " but its entry in SonList is " << SonList[FatherOfRunner->nr] << "!" << endl;
     3650    }
     3651    if ((LonelyFlag) && (size > 1)) {
     3652      *out << Verbose(0) << *Runner << "has got bonds only to hydrogens!" << endl;
     3653    }
    36543654#ifdef ADDHYDROGEN
    3655                 while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen
    3656                         Runner = Runner->next;
     3655    while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen
     3656      Runner = Runner->next;
    36573657#endif
    3658         }
    3659         Leaf->CreateListOfBondsPerAtom(out);
    3660         //Leaflet->Leaf->ScanForPeriodicCorrection(out);
    3661         Free((void **)&SonList, "molecule::StoreFragmentFromStack: **SonList");
    3662 //      *out << Verbose(1) << "End of StoreFragmentFromKeyset." << endl;
    3663         return Leaf;
     3658  }
     3659  Leaf->CreateListOfBondsPerAtom(out);
     3660  //Leaflet->Leaf->ScanForPeriodicCorrection(out);
     3661  Free((void **)&SonList, "molecule::StoreFragmentFromStack: **SonList");
     3662//  *out << Verbose(1) << "End of StoreFragmentFromKeyset." << endl;
     3663  return Leaf;
    36643664};
    36653665
     
    36673667 */
    36683668struct UniqueFragments {
    3669         config *configuration;
    3670         atom *Root;
    3671         Graph *Leaflet;
    3672         KeySet *FragmentSet;
    3673         int ANOVAOrder;
    3674         int FragmentCounter;
    3675         int CurrentIndex;
    3676         double TEFactor;
    3677         int *ShortestPathList;
    3678         bool **UsedList;
    3679         bond **BondsPerSPList;
    3680         int *BondsPerSPCount;
     3669  config *configuration;
     3670  atom *Root;
     3671  Graph *Leaflet;
     3672  KeySet *FragmentSet;
     3673  int ANOVAOrder;
     3674  int FragmentCounter;
     3675  int CurrentIndex;
     3676  double TEFactor;
     3677  int *ShortestPathList;
     3678  bool **UsedList;
     3679  bond **BondsPerSPList;
     3680  int *BondsPerSPCount;
    36813681};
    36823682
    36833683/** From a given set of Bond sorted by Shortest Path distance, create all possible fragments of size \a SetDimension.
    36843684 * -# loops over every possible combination (2^dimension of edge set)
    3685  *      -# inserts current set, if there's still space left
    3686  *              -# yes: calls SPFragmentGenerator with structure, created new edge list and size respective to root dist
     3685 *  -# inserts current set, if there's still space left
     3686 *    -# yes: calls SPFragmentGenerator with structure, created new edge list and size respective to root dist
    36873687ance+1
    3688  *              -# no: stores fragment into keyset list by calling InsertFragmentIntoGraph
    3689  *      -# removes all items added into the snake stack (in UniqueFragments structure) added during level (root
     3688 *    -# no: stores fragment into keyset list by calling InsertFragmentIntoGraph
     3689 *  -# removes all items added into the snake stack (in UniqueFragments structure) added during level (root
    36903690distance) and current set
    36913691 * \param *out output stream for debugging
     
    36973697void molecule::SPFragmentGenerator(ofstream *out, struct UniqueFragments *FragmentSearch, int RootDistance, bond **BondsSet, int SetDimension, int SubOrder)
    36983698{
    3699         atom *OtherWalker = NULL;
    3700         int verbosity = 0; //FragmentSearch->ANOVAOrder-SubOrder;
    3701         int NumCombinations;
    3702         bool bit;
    3703         int bits, TouchedIndex, SubSetDimension, SP, Added;
    3704         int Removal;
    3705         int SpaceLeft;
    3706         int *TouchedList = (int *) Malloc(sizeof(int)*(SubOrder+1), "molecule::SPFragmentGenerator: *TouchedList");
    3707         bond *Binder = NULL;
    3708         bond **BondsList = NULL;
    3709         KeySetTestPair TestKeySetInsert;
    3710 
    3711         NumCombinations = 1 << SetDimension;
    3712 
    3713         // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen
    3714         // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder
    3715         // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden
    3716 
    3717         *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl;
    3718         *out << Verbose(1+verbosity) << "We are " << RootDistance << " away from Root, which is " << *FragmentSearch->Root << ", SubOrder is " << SubOrder << ", SetDimension is " << SetDimension << " and this means " <<     NumCombinations-1 << " combination(s)." << endl;
    3719 
    3720         // initialised touched list (stores added atoms on this level)
    3721         *out << Verbose(1+verbosity) << "Clearing touched list." << endl;
    3722         for (TouchedIndex=SubOrder+1;TouchedIndex--;)   // empty touched list
    3723                 TouchedList[TouchedIndex] = -1;
    3724         TouchedIndex = 0;
    3725 
    3726         // create every possible combination of the endpieces
    3727         *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl;
    3728         for (int i=1;i<NumCombinations;i++) {   // sweep through all power set combinations (skip empty set!)
    3729                 // count the set bit of i
    3730                 bits = 0;
    3731                 for (int j=SetDimension;j--;)
    3732                         bits += (i & (1 << j)) >> j;
    3733 
    3734                 *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl;
    3735                 if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue
    3736                         // --1-- add this set of the power set of bond partners to the snake stack
    3737                         Added = 0;
    3738                         for (int j=0;j<SetDimension;j++) {      // pull out every bit by shifting
    3739                                 bit = ((i & (1 << j)) != 0);    // mask the bit for the j-th bond
    3740                                 if (bit) {      // if bit is set, we add this bond partner
    3741                                         OtherWalker = BondsSet[j]->rightatom;   // rightatom is always the one more distant, i.e. the one to add
    3742                                         //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl;
    3743                                         *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl;
    3744                                         TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr);
    3745                                         if (TestKeySetInsert.second) {
    3746                                                 TouchedList[TouchedIndex++] = OtherWalker->nr;  // note as added
    3747                                                 Added++;
    3748                                         } else {
    3749                                                 *out << Verbose(2+verbosity) << "This was item was already present in the keyset." << endl;
    3750                                         }
    3751                                                 //FragmentSearch->UsedList[OtherWalker->nr][i] = true;
    3752                                         //}
    3753                                 } else {
    3754                                         *out << Verbose(2+verbosity) << "Not adding." << endl;
    3755                                 }
    3756                         }
    3757 
    3758                         SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore
    3759                         if (SpaceLeft > 0) {
    3760                                 *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl;
    3761                                 if (SubOrder > 1) {             // Due to Added above we have to check extra whether we're not already reaching beyond the desired Order
    3762                                         // --2-- look at all added end pieces of this combination, construct bond subsets and sweep through a power set of these by recursion
    3763                                         SP = RootDistance+1;    // this is the next level
    3764                                         // first count the members in the subset
    3765                                         SubSetDimension = 0;
    3766                                         Binder = FragmentSearch->BondsPerSPList[2*SP];          // start node for this level
    3767                                         while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) {                // compare to end node of this level
    3768                                                 Binder = Binder->next;
    3769                                                 for (int k=TouchedIndex;k--;) {
    3770                                                         if (Binder->Contains(TouchedList[k]))    // if we added this very endpiece
    3771                                                                 SubSetDimension++;
    3772                                                 }
    3773                                         }
    3774                                         // then allocate and fill the list
    3775                                         BondsList = (bond **) Malloc(sizeof(bond *)*SubSetDimension, "molecule::SPFragmentGenerator: **BondsList");
    3776                                         SubSetDimension = 0;
    3777                                         Binder = FragmentSearch->BondsPerSPList[2*SP];
    3778                                         while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) {
    3779                                                 Binder = Binder->next;
    3780                                                 for (int k=0;k<TouchedIndex;k++) {
    3781                                                         if (Binder->leftatom->nr == TouchedList[k])      // leftatom is always the close one
    3782                                                                 BondsList[SubSetDimension++] = Binder;
    3783                                                 }
    3784                                         }
    3785                                         *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl;
    3786                                         SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits);
    3787                                         Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList");
    3788                                 }
    3789                         } else {
    3790                                 // --2-- otherwise store the complete fragment
    3791                                 *out << Verbose(1+verbosity) << "Enough items on stack for a fragment!" << endl;
    3792                                 // store fragment as a KeySet
    3793                                 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: ";
    3794                                 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++)
    3795                                         *out << (*runner) << " ";
    3796                                 *out << endl;
    3797                                 //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet))
    3798                                         //*out << Verbose(0) << "ERROR: The found fragment is not a connected subgraph!" << endl;
    3799                                 InsertFragmentIntoGraph(out, FragmentSearch);
    3800                                 //Removal = LookForRemovalCandidate(out, FragmentSearch->FragmentSet, FragmentSearch->ShortestPathList);
    3801                                 //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration);
    3802                         }
    3803 
    3804                         // --3-- remove all added items in this level from snake stack
    3805                         *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl;
    3806                         for(int j=0;j<TouchedIndex;j++) {
    3807                                 Removal = TouchedList[j];
    3808                                 *out << Verbose(2+verbosity) << "Removing item nr. " << Removal << " from snake stack." << endl;
    3809                                 FragmentSearch->FragmentSet->erase(Removal);
    3810                                 TouchedList[j] = -1;
    3811                         }
    3812                         *out << Verbose(2) << "Remaining local nr.s on snake stack are: ";
    3813                         for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++)
    3814                                 *out << (*runner) << " ";
    3815                         *out << endl;
    3816                         TouchedIndex = 0; // set Index to 0 for list of atoms added on this level
    3817                 } else {
    3818                         *out << Verbose(2+verbosity) << "More atoms to add for this set (" << bits << ") than space left on stack " << SubOrder << ", skipping this set." << endl;
    3819                 }
    3820         }
    3821         Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList");
    3822         *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl;
     3699  atom *OtherWalker = NULL;
     3700  int verbosity = 0; //FragmentSearch->ANOVAOrder-SubOrder;
     3701  int NumCombinations;
     3702  bool bit;
     3703  int bits, TouchedIndex, SubSetDimension, SP, Added;
     3704  int Removal;
     3705  int SpaceLeft;
     3706  int *TouchedList = (int *) Malloc(sizeof(int)*(SubOrder+1), "molecule::SPFragmentGenerator: *TouchedList");
     3707  bond *Binder = NULL;
     3708  bond **BondsList = NULL;
     3709  KeySetTestPair TestKeySetInsert;
     3710
     3711  NumCombinations = 1 << SetDimension;
     3712
     3713  // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen
     3714  // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder
     3715  // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden
     3716
     3717  *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl;
     3718  *out << Verbose(1+verbosity) << "We are " << RootDistance << " away from Root, which is " << *FragmentSearch->Root << ", SubOrder is " << SubOrder << ", SetDimension is " << SetDimension << " and this means " <<  NumCombinations-1 << " combination(s)." << endl;
     3719
     3720  // initialised touched list (stores added atoms on this level)
     3721  *out << Verbose(1+verbosity) << "Clearing touched list." << endl;
     3722  for (TouchedIndex=SubOrder+1;TouchedIndex--;)  // empty touched list
     3723    TouchedList[TouchedIndex] = -1;
     3724  TouchedIndex = 0;
     3725
     3726  // create every possible combination of the endpieces
     3727  *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl;
     3728  for (int i=1;i<NumCombinations;i++) {  // sweep through all power set combinations (skip empty set!)
     3729    // count the set bit of i
     3730    bits = 0;
     3731    for (int j=SetDimension;j--;)
     3732      bits += (i & (1 << j)) >> j;
     3733
     3734    *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl;
     3735    if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue
     3736      // --1-- add this set of the power set of bond partners to the snake stack
     3737      Added = 0;
     3738      for (int j=0;j<SetDimension;j++) {  // pull out every bit by shifting
     3739        bit = ((i & (1 << j)) != 0);  // mask the bit for the j-th bond
     3740        if (bit) {  // if bit is set, we add this bond partner
     3741          OtherWalker = BondsSet[j]->rightatom;  // rightatom is always the one more distant, i.e. the one to add
     3742          //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl;
     3743          *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl;
     3744          TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr);
     3745          if (TestKeySetInsert.second) {
     3746            TouchedList[TouchedIndex++] = OtherWalker->nr;  // note as added
     3747            Added++;
     3748          } else {
     3749            *out << Verbose(2+verbosity) << "This was item was already present in the keyset." << endl;
     3750          }
     3751            //FragmentSearch->UsedList[OtherWalker->nr][i] = true;
     3752          //}
     3753        } else {
     3754          *out << Verbose(2+verbosity) << "Not adding." << endl;
     3755        }
     3756      }
     3757
     3758      SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore
     3759      if (SpaceLeft > 0) {
     3760        *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl;
     3761        if (SubOrder > 1) {    // Due to Added above we have to check extra whether we're not already reaching beyond the desired Order
     3762          // --2-- look at all added end pieces of this combination, construct bond subsets and sweep through a power set of these by recursion
     3763          SP = RootDistance+1;  // this is the next level
     3764          // first count the members in the subset
     3765          SubSetDimension = 0;
     3766          Binder = FragmentSearch->BondsPerSPList[2*SP];    // start node for this level
     3767          while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) {    // compare to end node of this level
     3768            Binder = Binder->next;
     3769            for (int k=TouchedIndex;k--;) {
     3770              if (Binder->Contains(TouchedList[k]))  // if we added this very endpiece
     3771                SubSetDimension++;
     3772            }
     3773          }
     3774          // then allocate and fill the list
     3775          BondsList = (bond **) Malloc(sizeof(bond *)*SubSetDimension, "molecule::SPFragmentGenerator: **BondsList");
     3776          SubSetDimension = 0;
     3777          Binder = FragmentSearch->BondsPerSPList[2*SP];
     3778          while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) {
     3779            Binder = Binder->next;
     3780            for (int k=0;k<TouchedIndex;k++) {
     3781              if (Binder->leftatom->nr == TouchedList[k])  // leftatom is always the close one
     3782                BondsList[SubSetDimension++] = Binder;
     3783            }
     3784          }
     3785          *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl;
     3786          SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits);
     3787          Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList");
     3788        }
     3789      } else {
     3790        // --2-- otherwise store the complete fragment
     3791        *out << Verbose(1+verbosity) << "Enough items on stack for a fragment!" << endl;
     3792        // store fragment as a KeySet
     3793        *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: ";
     3794        for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++)
     3795          *out << (*runner) << " ";
     3796        *out << endl;
     3797        //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet))
     3798          //*out << Verbose(0) << "ERROR: The found fragment is not a connected subgraph!" << endl;
     3799        InsertFragmentIntoGraph(out, FragmentSearch);
     3800        //Removal = LookForRemovalCandidate(out, FragmentSearch->FragmentSet, FragmentSearch->ShortestPathList);
     3801        //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration);
     3802      }
     3803
     3804      // --3-- remove all added items in this level from snake stack
     3805      *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl;
     3806      for(int j=0;j<TouchedIndex;j++) {
     3807        Removal = TouchedList[j];
     3808        *out << Verbose(2+verbosity) << "Removing item nr. " << Removal << " from snake stack." << endl;
     3809        FragmentSearch->FragmentSet->erase(Removal);
     3810        TouchedList[j] = -1;
     3811      }
     3812      *out << Verbose(2) << "Remaining local nr.s on snake stack are: ";
     3813      for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++)
     3814        *out << (*runner) << " ";
     3815      *out << endl;
     3816      TouchedIndex = 0; // set Index to 0 for list of atoms added on this level
     3817    } else {
     3818      *out << Verbose(2+verbosity) << "More atoms to add for this set (" << bits << ") than space left on stack " << SubOrder << ", skipping this set." << endl;
     3819    }
     3820  }
     3821  Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList");
     3822  *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl;
    38233823};
    38243824
     
    38313831bool molecule::CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment)
    38323832{
    3833         atom *Walker = NULL, *Walker2 = NULL;
    3834         bool BondStatus = false;
    3835         int size;
    3836 
    3837         *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl;
    3838         *out << Verbose(2) << "Disconnected atom: ";
    3839 
    3840         // count number of atoms in graph
    3841         size = 0;
    3842         for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++)
    3843                 size++;
    3844         if (size > 1)
    3845                 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) {
    3846                         Walker = FindAtom(*runner);
    3847                         BondStatus = false;
    3848                         for(KeySet::iterator runners = Fragment->begin(); runners != Fragment->end(); runners++) {
    3849                                 Walker2 = FindAtom(*runners);
    3850                                 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {
    3851                                         if (ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker) == Walker2) {
    3852                                                 BondStatus = true;
    3853                                                 break;
    3854                                         }
    3855                                         if (BondStatus)
    3856                                                 break;
    3857                                 }
    3858                         }
    3859                         if (!BondStatus) {
    3860                                 *out << (*Walker) << endl;
    3861                                 return false;
    3862                         }
    3863                 }
    3864         else {
    3865                 *out << "none." << endl;
    3866                 return true;
    3867         }
    3868         *out << "none." << endl;
    3869 
    3870         *out << Verbose(1) << "End of CheckForConnectedSubgraph" << endl;
    3871 
    3872         return true;
     3833  atom *Walker = NULL, *Walker2 = NULL;
     3834  bool BondStatus = false;
     3835  int size;
     3836
     3837  *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl;
     3838  *out << Verbose(2) << "Disconnected atom: ";
     3839
     3840  // count number of atoms in graph
     3841  size = 0;
     3842  for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++)
     3843    size++;
     3844  if (size > 1)
     3845    for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) {
     3846      Walker = FindAtom(*runner);
     3847      BondStatus = false;
     3848      for(KeySet::iterator runners = Fragment->begin(); runners != Fragment->end(); runners++) {
     3849        Walker2 = FindAtom(*runners);
     3850        for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {
     3851          if (ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker) == Walker2) {
     3852            BondStatus = true;
     3853            break;
     3854          }
     3855          if (BondStatus)
     3856            break;
     3857        }
     3858      }
     3859      if (!BondStatus) {
     3860        *out << (*Walker) << endl;
     3861        return false;
     3862      }
     3863    }
     3864  else {
     3865    *out << "none." << endl;
     3866    return true;
     3867  }
     3868  *out << "none." << endl;
     3869
     3870  *out << Verbose(1) << "End of CheckForConnectedSubgraph" << endl;
     3871
     3872  return true;
    38733873}
    38743874
     
    38903890int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet)
    38913891{
    3892         int SP, AtomKeyNr;
    3893         atom *Walker = NULL, *OtherWalker = NULL, *Predecessor = NULL;
    3894         bond *Binder = NULL;
    3895         bond *CurrentEdge = NULL;
    3896         bond **BondsList = NULL;
    3897         int RootKeyNr = FragmentSearch.Root->GetTrueFather()->nr;
    3898         int Counter = FragmentSearch.FragmentCounter;
    3899         int RemainingWalkers;
    3900 
    3901         *out << endl;
    3902         *out << Verbose(0) << "Begin of PowerSetGenerator with order " << Order << " at Root " << *FragmentSearch.Root << "." << endl;
    3903 
    3904         // prepare Label and SP arrays of the BFS search
    3905         FragmentSearch.ShortestPathList[FragmentSearch.Root->nr] = 0;
    3906 
    3907         // prepare root level (SP = 0) and a loop bond denoting Root
    3908         for (int i=1;i<Order;i++)
    3909                 FragmentSearch.BondsPerSPCount[i] = 0;
    3910         FragmentSearch.BondsPerSPCount[0] = 1;
    3911         Binder = new bond(FragmentSearch.Root, FragmentSearch.Root);
    3912         add(Binder, FragmentSearch.BondsPerSPList[1]);
    3913 
    3914         // do a BFS search to fill the SP lists and label the found vertices
    3915         // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into
    3916         // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning
    3917         // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth
    3918         // (EdgeinSPLevel) of this tree ...
    3919         // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence
    3920         // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction.
    3921         *out << endl;
    3922         *out << Verbose(0) << "Starting BFS analysis ..." << endl;
    3923         for (SP = 0; SP < (Order-1); SP++) {
    3924                 *out << Verbose(1) << "New SP level reached: " << SP << ", creating new SP list with " << FragmentSearch.BondsPerSPCount[SP] << " item(s)";
    3925                 if (SP > 0) {
    3926                         *out << ", old level closed with " << FragmentSearch.BondsPerSPCount[SP-1] << " item(s)." << endl;
    3927                         FragmentSearch.BondsPerSPCount[SP] = 0;
    3928                 } else
    3929                         *out << "." << endl;
    3930 
    3931                 RemainingWalkers = FragmentSearch.BondsPerSPCount[SP];
    3932                 CurrentEdge = FragmentSearch.BondsPerSPList[2*SP];              /// start of this SP level's list
    3933                 while (CurrentEdge->next != FragmentSearch.BondsPerSPList[2*SP+1]) {            /// end of this SP level's list
    3934                         CurrentEdge = CurrentEdge->next;
    3935                         RemainingWalkers--;
    3936                         Walker = CurrentEdge->rightatom;                // rightatom is always the one more distant
    3937                         Predecessor = CurrentEdge->leftatom;            // ... and leftatom is predecessor
    3938                         AtomKeyNr = Walker->nr;
    3939                         *out << Verbose(0) << "Current Walker is: " << *Walker << " with nr " << Walker->nr << " and SP of " << SP << ", with " << RemainingWalkers << " remaining walkers on this level." << endl;
    3940                         // check for new sp level
    3941                         // go through all its bonds
    3942                         *out << Verbose(1) << "Going through all bonds of Walker." << endl;
    3943                         for (int i=0;i<NumberOfBondsPerAtom[AtomKeyNr];i++) {
    3944                                 Binder = ListOfBondsPerAtom[AtomKeyNr][i];
    3945                                 OtherWalker = Binder->GetOtherAtom(Walker);
    3946                                 if ((RestrictedKeySet.find(OtherWalker->nr) != RestrictedKeySet.end())
    3947         #ifdef ADDHYDROGEN
    3948                                 && (OtherWalker->type->Z != 1)
    3949         #endif
    3950                                                                                                                                                                                                                                                         ) {     // skip hydrogens and restrict to fragment
    3951                                         *out << Verbose(2) << "Current partner is " << *OtherWalker << " with nr " << OtherWalker->nr << " in bond " << *Binder << "." << endl;
    3952                                         // set the label if not set (and push on root stack as well)
    3953                                         if ((OtherWalker != Predecessor) && (OtherWalker->GetTrueFather()->nr > RootKeyNr)) { // only pass through those with label bigger than Root's
    3954                                                 FragmentSearch.ShortestPathList[OtherWalker->nr] = SP+1;
    3955                                                 *out << Verbose(3) << "Set Shortest Path to " << FragmentSearch.ShortestPathList[OtherWalker->nr] << "." << endl;
    3956                                                 // add the bond in between to the SP list
    3957                                                 Binder = new bond(Walker, OtherWalker); // create a new bond in such a manner, that bond::rightatom is always the one more distant
    3958                                                 add(Binder, FragmentSearch.BondsPerSPList[2*(SP+1)+1]);
    3959                                                 FragmentSearch.BondsPerSPCount[SP+1]++;
    3960                                                 *out << Verbose(3) << "Added its bond to SP list, having now " << FragmentSearch.BondsPerSPCount[SP+1] << " item(s)." << endl;
    3961                                         } else {
    3962                                                 if (OtherWalker != Predecessor)
    3963                                                         *out << Verbose(3) << "Not passing on, as index of " << *OtherWalker << " " << OtherWalker->GetTrueFather()->nr << " is smaller than that of Root " << RootKeyNr << "." << endl;
    3964                                                 else
    3965                                                         *out << Verbose(3) << "This is my predecessor " << *Predecessor << "." << endl;
    3966                                         }
    3967                                 } else *out << Verbose(2) << "Is not in the restricted keyset or skipping hydrogen " << *OtherWalker << "." << endl;
    3968                         }
    3969                 }
    3970         }
    3971 
    3972         // outputting all list for debugging
    3973         *out << Verbose(0) << "Printing all found lists." << endl;
    3974         for(int i=1;i<Order;i++) {              // skip the root edge in the printing
    3975                 Binder = FragmentSearch.BondsPerSPList[2*i];
    3976                 *out << Verbose(1) << "Current SP level is " << i << "." << endl;
    3977                 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {
    3978                         Binder = Binder->next;
    3979                         *out << Verbose(2) << *Binder << endl;
    3980                 }
    3981         }
    3982 
    3983         // creating fragments with the found edge sets  (may be done in reverse order, faster)
    3984         SP = -1;        // the Root <-> Root edge must be subtracted!
    3985         for(int i=Order;i--;) { // sum up all found edges
    3986                 Binder = FragmentSearch.BondsPerSPList[2*i];
    3987                 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {
    3988                         Binder = Binder->next;
    3989                         SP ++;
    3990                 }
    3991         }
    3992         *out << Verbose(0) << "Total number of edges is " << SP << "." << endl;
    3993         if (SP >= (Order-1)) {
    3994                 // start with root (push on fragment stack)
    3995                 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl;
    3996                 FragmentSearch.FragmentSet->clear();
    3997                 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl;
    3998                 // prepare the subset and call the generator
    3999                 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList");
    4000                 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next;  // on SP level 0 there's only the root bond
    4001 
    4002                 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order);
    4003 
    4004                 Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList");
    4005         } else {
    4006                 *out << Verbose(0) << "Not enough total number of edges to build " << Order << "-body fragments." << endl;
    4007         }
    4008 
    4009         // as FragmentSearch structure is used only once, we don't have to clean it anymore
    4010         // remove root from stack
    4011         *out << Verbose(0) << "Removing root again from stack." << endl;
    4012         FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr);
    4013 
    4014         // free'ing the bonds lists
    4015         *out << Verbose(0) << "Free'ing all found lists. and resetting index lists" << endl;
    4016         for(int i=Order;i--;) {
    4017                 *out << Verbose(1) << "Current SP level is " << i << ": ";
    4018                 Binder = FragmentSearch.BondsPerSPList[2*i];
    4019                 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {
    4020                         Binder = Binder->next;
    4021                         // *out << "Removing atom " << Binder->leftatom->nr << " and " << Binder->rightatom->nr << "." << endl; // make sure numbers are local
    4022                         FragmentSearch.ShortestPathList[Binder->leftatom->nr] = -1;
    4023                         FragmentSearch.ShortestPathList[Binder->rightatom->nr] = -1;
    4024                 }
    4025                 // delete added bonds
    4026                 cleanup(FragmentSearch.BondsPerSPList[2*i], FragmentSearch.BondsPerSPList[2*i+1]);
    4027                 // also start and end node
    4028                 *out << "cleaned." << endl;
    4029         }
    4030 
    4031         // return list
    4032         *out << Verbose(0) << "End of PowerSetGenerator." << endl;
    4033         return (FragmentSearch.FragmentCounter - Counter);
     3892  int SP, AtomKeyNr;
     3893  atom *Walker = NULL, *OtherWalker = NULL, *Predecessor = NULL;
     3894  bond *Binder = NULL;
     3895  bond *CurrentEdge = NULL;
     3896  bond **BondsList = NULL;
     3897  int RootKeyNr = FragmentSearch.Root->GetTrueFather()->nr;
     3898  int Counter = FragmentSearch.FragmentCounter;
     3899  int RemainingWalkers;
     3900
     3901  *out << endl;
     3902  *out << Verbose(0) << "Begin of PowerSetGenerator with order " << Order << " at Root " << *FragmentSearch.Root << "." << endl;
     3903
     3904  // prepare Label and SP arrays of the BFS search
     3905  FragmentSearch.ShortestPathList[FragmentSearch.Root->nr] = 0;
     3906
     3907  // prepare root level (SP = 0) and a loop bond denoting Root
     3908  for (int i=1;i<Order;i++)
     3909    FragmentSearch.BondsPerSPCount[i] = 0;
     3910  FragmentSearch.BondsPerSPCount[0] = 1;
     3911  Binder = new bond(FragmentSearch.Root, FragmentSearch.Root);
     3912  add(Binder, FragmentSearch.BondsPerSPList[1]);
     3913
     3914  // do a BFS search to fill the SP lists and label the found vertices
     3915  // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into
     3916  // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning
     3917  // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth
     3918  // (EdgeinSPLevel) of this tree ...
     3919  // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence
     3920  // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction.
     3921  *out << endl;
     3922  *out << Verbose(0) << "Starting BFS analysis ..." << endl;
     3923  for (SP = 0; SP < (Order-1); SP++) {
     3924    *out << Verbose(1) << "New SP level reached: " << SP << ", creating new SP list with " << FragmentSearch.BondsPerSPCount[SP] << " item(s)";
     3925    if (SP > 0) {
     3926      *out << ", old level closed with " << FragmentSearch.BondsPerSPCount[SP-1] << " item(s)." << endl;
     3927      FragmentSearch.BondsPerSPCount[SP] = 0;
     3928    } else
     3929      *out << "." << endl;
     3930
     3931    RemainingWalkers = FragmentSearch.BondsPerSPCount[SP];
     3932    CurrentEdge = FragmentSearch.BondsPerSPList[2*SP];    /// start of this SP level's list
     3933    while (CurrentEdge->next != FragmentSearch.BondsPerSPList[2*SP+1]) {    /// end of this SP level's list
     3934      CurrentEdge = CurrentEdge->next;
     3935      RemainingWalkers--;
     3936      Walker = CurrentEdge->rightatom;    // rightatom is always the one more distant
     3937      Predecessor = CurrentEdge->leftatom;    // ... and leftatom is predecessor
     3938      AtomKeyNr = Walker->nr;
     3939      *out << Verbose(0) << "Current Walker is: " << *Walker << " with nr " << Walker->nr << " and SP of " << SP << ", with " << RemainingWalkers << " remaining walkers on this level." << endl;
     3940      // check for new sp level
     3941      // go through all its bonds
     3942      *out << Verbose(1) << "Going through all bonds of Walker." << endl;
     3943      for (int i=0;i<NumberOfBondsPerAtom[AtomKeyNr];i++) {
     3944        Binder = ListOfBondsPerAtom[AtomKeyNr][i];
     3945        OtherWalker = Binder->GetOtherAtom(Walker);
     3946        if ((RestrictedKeySet.find(OtherWalker->nr) != RestrictedKeySet.end())
     3947  #ifdef ADDHYDROGEN
     3948        && (OtherWalker->type->Z != 1)
     3949  #endif
     3950                                                              ) {  // skip hydrogens and restrict to fragment
     3951          *out << Verbose(2) << "Current partner is " << *OtherWalker << " with nr " << OtherWalker->nr << " in bond " << *Binder << "." << endl;
     3952          // set the label if not set (and push on root stack as well)
     3953          if ((OtherWalker != Predecessor) && (OtherWalker->GetTrueFather()->nr > RootKeyNr)) { // only pass through those with label bigger than Root's
     3954            FragmentSearch.ShortestPathList[OtherWalker->nr] = SP+1;
     3955            *out << Verbose(3) << "Set Shortest Path to " << FragmentSearch.ShortestPathList[OtherWalker->nr] << "." << endl;
     3956            // add the bond in between to the SP list
     3957            Binder = new bond(Walker, OtherWalker); // create a new bond in such a manner, that bond::rightatom is always the one more distant
     3958            add(Binder, FragmentSearch.BondsPerSPList[2*(SP+1)+1]);
     3959            FragmentSearch.BondsPerSPCount[SP+1]++;
     3960            *out << Verbose(3) << "Added its bond to SP list, having now " << FragmentSearch.BondsPerSPCount[SP+1] << " item(s)." << endl;
     3961          } else {
     3962            if (OtherWalker != Predecessor)
     3963              *out << Verbose(3) << "Not passing on, as index of " << *OtherWalker << " " << OtherWalker->GetTrueFather()->nr << " is smaller than that of Root " << RootKeyNr << "." << endl;
     3964            else
     3965              *out << Verbose(3) << "This is my predecessor " << *Predecessor << "." << endl;
     3966          }
     3967        } else *out << Verbose(2) << "Is not in the restricted keyset or skipping hydrogen " << *OtherWalker << "." << endl;
     3968      }
     3969    }
     3970  }
     3971
     3972  // outputting all list for debugging
     3973  *out << Verbose(0) << "Printing all found lists." << endl;
     3974  for(int i=1;i<Order;i++) {    // skip the root edge in the printing
     3975    Binder = FragmentSearch.BondsPerSPList[2*i];
     3976    *out << Verbose(1) << "Current SP level is " << i << "." << endl;
     3977    while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {
     3978      Binder = Binder->next;
     3979      *out << Verbose(2) << *Binder << endl;
     3980    }
     3981  }
     3982
     3983  // creating fragments with the found edge sets  (may be done in reverse order, faster)
     3984  SP = -1;  // the Root <-> Root edge must be subtracted!
     3985  for(int i=Order;i--;) { // sum up all found edges
     3986    Binder = FragmentSearch.BondsPerSPList[2*i];
     3987    while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {
     3988      Binder = Binder->next;
     3989      SP ++;
     3990    }
     3991  }
     3992  *out << Verbose(0) << "Total number of edges is " << SP << "." << endl;
     3993  if (SP >= (Order-1)) {
     3994    // start with root (push on fragment stack)
     3995    *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl;
     3996    FragmentSearch.FragmentSet->clear();
     3997    *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl;
     3998    // prepare the subset and call the generator
     3999    BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList");
     4000    BondsList[0] = FragmentSearch.BondsPerSPList[0]->next;  // on SP level 0 there's only the root bond
     4001
     4002    SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order);
     4003
     4004    Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList");
     4005  } else {
     4006    *out << Verbose(0) << "Not enough total number of edges to build " << Order << "-body fragments." << endl;
     4007  }
     4008
     4009  // as FragmentSearch structure is used only once, we don't have to clean it anymore
     4010  // remove root from stack
     4011  *out << Verbose(0) << "Removing root again from stack." << endl;
     4012  FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr);
     4013
     4014  // free'ing the bonds lists
     4015  *out << Verbose(0) << "Free'ing all found lists. and resetting index lists" << endl;
     4016  for(int i=Order;i--;) {
     4017    *out << Verbose(1) << "Current SP level is " << i << ": ";
     4018    Binder = FragmentSearch.BondsPerSPList[2*i];
     4019    while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {
     4020      Binder = Binder->next;
     4021      // *out << "Removing atom " << Binder->leftatom->nr << " and " << Binder->rightatom->nr << "." << endl; // make sure numbers are local
     4022      FragmentSearch.ShortestPathList[Binder->leftatom->nr] = -1;
     4023      FragmentSearch.ShortestPathList[Binder->rightatom->nr] = -1;
     4024    }
     4025    // delete added bonds
     4026    cleanup(FragmentSearch.BondsPerSPList[2*i], FragmentSearch.BondsPerSPList[2*i+1]);
     4027    // also start and end node
     4028    *out << "cleaned." << endl;
     4029  }
     4030
     4031  // return list
     4032  *out << Verbose(0) << "End of PowerSetGenerator." << endl;
     4033  return (FragmentSearch.FragmentCounter - Counter);
    40344034};
    40354035
     
    40424042void molecule::ScanForPeriodicCorrection(ofstream *out)
    40434043{
    4044         bond *Binder = NULL;
    4045         bond *OtherBinder = NULL;
    4046         atom *Walker = NULL;
    4047         atom *OtherWalker = NULL;
    4048         double *matrix = ReturnFullMatrixforSymmetric(cell_size);
    4049         enum Shading *ColorList = NULL;
    4050         double tmp;
    4051         Vector Translationvector;
    4052         //class StackClass<atom *> *CompStack = NULL;
    4053         class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);
    4054         bool flag = true;
    4055 
    4056         *out << Verbose(2) << "Begin of ScanForPeriodicCorrection." << endl;
    4057 
    4058         ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::ScanForPeriodicCorrection: *ColorList");
    4059         while (flag) {
    4060                 // remove bonds that are beyond bonddistance
    4061                 for(int i=NDIM;i--;)
    4062                         Translationvector.x[i] = 0.;
    4063                 // scan all bonds
    4064                 Binder = first;
    4065                 flag = false;
    4066                 while ((!flag) && (Binder->next != last)) {
    4067                         Binder = Binder->next;
    4068                         for (int i=NDIM;i--;) {
    4069                                 tmp = fabs(Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]);
    4070                                 //*out << Verbose(3) << "Checking " << i << "th distance of " << *Binder->leftatom << " to " << *Binder->rightatom << ": " << tmp << "." << endl;
    4071                                 if (tmp > BondDistance) {
    4072                                         OtherBinder = Binder->next; // note down binding partner for later re-insertion
    4073                                         unlink(Binder); // unlink bond
    4074                                         *out << Verbose(2) << "Correcting at bond " << *Binder << "." << endl;
    4075                                         flag = true;
    4076                                         break;
    4077                                 }
    4078                         }
    4079                 }
    4080                 if (flag) {
    4081                         // create translation vector from their periodically modified distance
    4082                         for (int i=NDIM;i--;) {
    4083                                 tmp = Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i];
    4084                                 if (fabs(tmp) > BondDistance)
    4085                                         Translationvector.x[i] = (tmp < 0) ? +1. : -1.;
    4086                         }
    4087                         Translationvector.MatrixMultiplication(matrix);
    4088                         //*out << Verbose(3) << "Translation vector is ";
    4089                         Translationvector.Output(out);
    4090                         *out << endl;
    4091                         // apply to all atoms of first component via BFS
    4092                         for (int i=AtomCount;i--;)
    4093                                 ColorList[i] = white;
    4094                         AtomStack->Push(Binder->leftatom);
    4095                         while (!AtomStack->IsEmpty()) {
    4096                                 Walker = AtomStack->PopFirst();
    4097                                 //*out << Verbose (3) << "Current Walker is: " << *Walker << "." << endl;
    4098                                 ColorList[Walker->nr] = black;          // mark as explored
    4099                                 Walker->x.AddVector(&Translationvector); // translate
    4100                                 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {  // go through all binding partners
    4101                                         if (ListOfBondsPerAtom[Walker->nr][i] != Binder) {
    4102                                                 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
    4103                                                 if (ColorList[OtherWalker->nr] == white) {
    4104                                                         AtomStack->Push(OtherWalker); // push if yet unexplored
    4105                                                 }
    4106                                         }
    4107                                 }
    4108                         }
    4109                         // re-add bond
    4110                         link(Binder, OtherBinder);
    4111                 } else {
    4112                         *out << Verbose(3) << "No corrections for this fragment." << endl;
    4113                 }
    4114                 //delete(CompStack);
    4115         }
    4116 
    4117         // free allocated space from ReturnFullMatrixforSymmetric()
    4118         delete(AtomStack);
    4119         Free((void **)&ColorList, "molecule::ScanForPeriodicCorrection: *ColorList");
    4120         Free((void **)&matrix, "molecule::ScanForPeriodicCorrection: *matrix");
    4121         *out << Verbose(2) << "End of ScanForPeriodicCorrection." << endl;
     4044  bond *Binder = NULL;
     4045  bond *OtherBinder = NULL;
     4046  atom *Walker = NULL;
     4047  atom *OtherWalker = NULL;
     4048  double *matrix = ReturnFullMatrixforSymmetric(cell_size);
     4049  enum Shading *ColorList = NULL;
     4050  double tmp;
     4051  Vector Translationvector;
     4052  //class StackClass<atom *> *CompStack = NULL;
     4053  class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);
     4054  bool flag = true;
     4055
     4056  *out << Verbose(2) << "Begin of ScanForPeriodicCorrection." << endl;
     4057
     4058  ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::ScanForPeriodicCorrection: *ColorList");
     4059  while (flag) {
     4060    // remove bonds that are beyond bonddistance
     4061    for(int i=NDIM;i--;)
     4062      Translationvector.x[i] = 0.;
     4063    // scan all bonds
     4064    Binder = first;
     4065    flag = false;
     4066    while ((!flag) && (Binder->next != last)) {
     4067      Binder = Binder->next;
     4068      for (int i=NDIM;i--;) {
     4069        tmp = fabs(Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]);
     4070        //*out << Verbose(3) << "Checking " << i << "th distance of " << *Binder->leftatom << " to " << *Binder->rightatom << ": " << tmp << "." << endl;
     4071        if (tmp > BondDistance) {
     4072          OtherBinder = Binder->next; // note down binding partner for later re-insertion
     4073          unlink(Binder);  // unlink bond
     4074          *out << Verbose(2) << "Correcting at bond " << *Binder << "." << endl;
     4075          flag = true;
     4076          break;
     4077        }
     4078      }
     4079    }
     4080    if (flag) {
     4081      // create translation vector from their periodically modified distance
     4082      for (int i=NDIM;i--;) {
     4083        tmp = Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i];
     4084        if (fabs(tmp) > BondDistance)
     4085          Translationvector.x[i] = (tmp < 0) ? +1. : -1.;
     4086      }
     4087      Translationvector.MatrixMultiplication(matrix);
     4088      //*out << Verbose(3) << "Translation vector is ";
     4089      Translationvector.Output(out);
     4090      *out << endl;
     4091      // apply to all atoms of first component via BFS
     4092      for (int i=AtomCount;i--;)
     4093        ColorList[i] = white;
     4094      AtomStack->Push(Binder->leftatom);
     4095      while (!AtomStack->IsEmpty()) {
     4096        Walker = AtomStack->PopFirst();
     4097        //*out << Verbose (3) << "Current Walker is: " << *Walker << "." << endl;
     4098        ColorList[Walker->nr] = black;    // mark as explored
     4099        Walker->x.AddVector(&Translationvector); // translate
     4100        for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {  // go through all binding partners
     4101          if (ListOfBondsPerAtom[Walker->nr][i] != Binder) {
     4102            OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
     4103            if (ColorList[OtherWalker->nr] == white) {
     4104              AtomStack->Push(OtherWalker); // push if yet unexplored
     4105            }
     4106          }
     4107        }
     4108      }
     4109      // re-add bond
     4110      link(Binder, OtherBinder);
     4111    } else {
     4112      *out << Verbose(3) << "No corrections for this fragment." << endl;
     4113    }
     4114    //delete(CompStack);
     4115  }
     4116
     4117  // free allocated space from ReturnFullMatrixforSymmetric()
     4118  delete(AtomStack);
     4119  Free((void **)&ColorList, "molecule::ScanForPeriodicCorrection: *ColorList");
     4120  Free((void **)&matrix, "molecule::ScanForPeriodicCorrection: *matrix");
     4121  *out << Verbose(2) << "End of ScanForPeriodicCorrection." << endl;
    41224122};
    41234123
     
    41284128double * molecule::ReturnFullMatrixforSymmetric(double *symm)
    41294129{
    4130         double *matrix = (double *) Malloc(sizeof(double)*NDIM*NDIM, "molecule::ReturnFullMatrixforSymmetric: *matrix");
    4131         matrix[0] = symm[0];
    4132         matrix[1] = symm[1];
    4133         matrix[2] = symm[3];
    4134         matrix[3] = symm[1];
    4135         matrix[4] = symm[2];
    4136         matrix[5] = symm[4];
    4137         matrix[6] = symm[3];
    4138         matrix[7] = symm[4];
    4139         matrix[8] = symm[5];
    4140         return matrix;
     4130  double *matrix = (double *) Malloc(sizeof(double)*NDIM*NDIM, "molecule::ReturnFullMatrixforSymmetric: *matrix");
     4131  matrix[0] = symm[0];
     4132  matrix[1] = symm[1];
     4133  matrix[2] = symm[3];
     4134  matrix[3] = symm[1];
     4135  matrix[4] = symm[2];
     4136  matrix[5] = symm[4];
     4137  matrix[6] = symm[3];
     4138  matrix[7] = symm[4];
     4139  matrix[8] = symm[5];
     4140  return matrix;
    41414141};
    41424142
    41434143bool KeyCompare::operator() (const KeySet SubgraphA, const KeySet SubgraphB) const
    41444144{
    4145         //cout << "my check is used." << endl;
    4146         if (SubgraphA.size() < SubgraphB.size()) {
    4147                 return true;
    4148         } else {
    4149                 if (SubgraphA.size() > SubgraphB.size()) {
    4150                         return false;
    4151                 } else {
    4152                         KeySet::iterator IteratorA = SubgraphA.begin();
    4153                         KeySet::iterator IteratorB = SubgraphB.begin();
    4154                         while ((IteratorA != SubgraphA.end()) && (IteratorB != SubgraphB.end())) {
    4155                                 if ((*IteratorA) <      (*IteratorB))
    4156                                         return true;
    4157                                 else if ((*IteratorA) > (*IteratorB)) {
    4158                                                 return false;
    4159                                         } // else, go on to next index
    4160                                 IteratorA++;
    4161                                 IteratorB++;
    4162                         } // end of while loop
    4163                 }// end of check in case of equal sizes
    4164         }
    4165         return false; // if we reach this point, they are equal
     4145  //cout << "my check is used." << endl;
     4146  if (SubgraphA.size() < SubgraphB.size()) {
     4147    return true;
     4148  } else {
     4149    if (SubgraphA.size() > SubgraphB.size()) {
     4150      return false;
     4151    } else {
     4152      KeySet::iterator IteratorA = SubgraphA.begin();
     4153      KeySet::iterator IteratorB = SubgraphB.begin();
     4154      while ((IteratorA != SubgraphA.end()) && (IteratorB != SubgraphB.end())) {
     4155        if ((*IteratorA) <  (*IteratorB))
     4156          return true;
     4157        else if ((*IteratorA) > (*IteratorB)) {
     4158            return false;
     4159          } // else, go on to next index
     4160        IteratorA++;
     4161        IteratorB++;
     4162      } // end of while loop
     4163    }// end of check in case of equal sizes
     4164  }
     4165  return false; // if we reach this point, they are equal
    41664166};
    41674167
    41684168//bool operator < (KeySet SubgraphA, KeySet SubgraphB)
    41694169//{
    4170 //      return KeyCompare(SubgraphA, SubgraphB);
     4170//  return KeyCompare(SubgraphA, SubgraphB);
    41714171//};
    41724172
     
    41804180inline void InsertFragmentIntoGraph(ofstream *out, struct UniqueFragments *Fragment)
    41814181{
    4182         GraphTestPair testGraphInsert;
    4183 
    4184         testGraphInsert = Fragment->Leaflet->insert(GraphPair (*Fragment->FragmentSet,pair<int,double>(Fragment->FragmentCounter,Fragment->TEFactor))); // store fragment number and current factor
    4185         if (testGraphInsert.second) {
    4186                 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " successfully inserted." << endl;
    4187                 Fragment->FragmentCounter++;
    4188         } else {
    4189                 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;
    4190                 ((*(testGraphInsert.first)).second).second += Fragment->TEFactor;       // increase the "created" counter
    4191                 *out << Verbose(2) << "New factor is " << ((*(testGraphInsert.first)).second).second << "." << endl;
    4192         }
     4182  GraphTestPair testGraphInsert;
     4183
     4184  testGraphInsert = Fragment->Leaflet->insert(GraphPair (*Fragment->FragmentSet,pair<int,double>(Fragment->FragmentCounter,Fragment->TEFactor)));  // store fragment number and current factor
     4185  if (testGraphInsert.second) {
     4186    *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " successfully inserted." << endl;
     4187    Fragment->FragmentCounter++;
     4188  } else {
     4189    *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;
     4190    ((*(testGraphInsert.first)).second).second += Fragment->TEFactor;  // increase the "created" counter
     4191    *out << Verbose(2) << "New factor is " << ((*(testGraphInsert.first)).second).second << "." << endl;
     4192  }
    41934193};
    41944194//void inline InsertIntoGraph(ofstream *out, KeyStack &stack, Graph &graph, int *counter, double factor)
    41954195//{
    4196 //      // copy stack contents to set and call overloaded function again
    4197 //      KeySet set;
    4198 //      for(KeyStack::iterator runner = stack.begin(); runner != stack.begin(); runner++)
    4199 //              set.insert((*runner));
    4200 //      InsertIntoGraph(out, set, graph, counter, factor);
     4196//  // copy stack contents to set and call overloaded function again
     4197//  KeySet set;
     4198//  for(KeyStack::iterator runner = stack.begin(); runner != stack.begin(); runner++)
     4199//    set.insert((*runner));
     4200//  InsertIntoGraph(out, set, graph, counter, factor);
    42014201//};
    42024202
     
    42094209inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter)
    42104210{
    4211         GraphTestPair testGraphInsert;
    4212 
    4213         for(Graph::iterator runner = graph2.begin(); runner != graph2.end(); runner++) {
    4214                 testGraphInsert = graph1.insert(GraphPair ((*runner).first,pair<int,double>((*counter)++,((*runner).second).second)));  // store fragment number and current factor
    4215                 if (testGraphInsert.second) {
    4216                         *out << Verbose(2) << "KeySet " << (*counter)-1 << " successfully inserted." << endl;
    4217                 } else {
    4218                         *out << Verbose(2) << "KeySet " << (*counter)-1 << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;
    4219                         ((*(testGraphInsert.first)).second).second += (*runner).second.second;
    4220                         *out << Verbose(2) << "New factor is " << (*(testGraphInsert.first)).second.second << "." << endl;
    4221                 }
    4222         }
     4211  GraphTestPair testGraphInsert;
     4212
     4213  for(Graph::iterator runner = graph2.begin(); runner != graph2.end(); runner++) {
     4214    testGraphInsert = graph1.insert(GraphPair ((*runner).first,pair<int,double>((*counter)++,((*runner).second).second)));  // store fragment number and current factor
     4215    if (testGraphInsert.second) {
     4216      *out << Verbose(2) << "KeySet " << (*counter)-1 << " successfully inserted." << endl;
     4217    } else {
     4218      *out << Verbose(2) << "KeySet " << (*counter)-1 << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;
     4219      ((*(testGraphInsert.first)).second).second += (*runner).second.second;
     4220      *out << Verbose(2) << "New factor is " << (*(testGraphInsert.first)).second.second << "." << endl;
     4221    }
     4222  }
    42234223};
    42244224
     
    42274227 * -# constructs a complete keyset of the molecule
    42284228 * -# In a loop over all possible roots from the given rootstack
    4229  *      -# increases order of root site
    4230  *      -# calls PowerSetGenerator with this order, the complete keyset and the rootkeynr
    4231  *      -# for all consecutive lower levels PowerSetGenerator is called with the suborder, the higher order keyset
     4229 *  -# increases order of root site
     4230 *  -# calls PowerSetGenerator with this order, the complete keyset and the rootkeynr
     4231 *  -# for all consecutive lower levels PowerSetGenerator is called with the suborder, the higher order keyset
    42324232as the restricted one and each site in the set as the root)
    4233  *      -# these are merged into a fragment list of keysets
     4233 *  -# these are merged into a fragment list of keysets
    42344234 * -# All fragment lists (for all orders, i.e. from all destination fields) are merged into one list for return
    42354235 * Important only is that we create all fragments, it is not important if we create them more than once
     
    42434243void molecule::FragmentBOSSANOVA(ofstream *out, Graph *&FragmentList, KeyStack &RootStack, int *MinimumRingSize)
    42444244{
    4245         Graph ***FragmentLowerOrdersList = NULL;
    4246         int NumLevels, NumMolecules, TotalNumMolecules = 0, *NumMoleculesOfOrder = NULL;
    4247         int counter = 0, Order;
    4248         int UpgradeCount = RootStack.size();
    4249         KeyStack FragmentRootStack;
    4250         int RootKeyNr, RootNr;
    4251         struct UniqueFragments FragmentSearch;
    4252 
    4253         *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl;
    4254 
    4255         // FragmentLowerOrdersList is a 2D-array of pointer to MoleculeListClass objects, one dimension represents the ANOVA expansion of a single order (i.e. 5)
    4256         // with all needed lower orders that are subtracted, the other dimension is the BondOrder (i.e. from 1 to 5)
    4257         NumMoleculesOfOrder = (int *) Malloc(sizeof(int)*UpgradeCount, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder");
    4258         FragmentLowerOrdersList = (Graph ***) Malloc(sizeof(Graph **)*UpgradeCount, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList");
    4259 
    4260         // initialise the fragments structure
    4261         FragmentSearch.ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::PowerSetGenerator: *ShortestPathList");
    4262         FragmentSearch.FragmentCounter = 0;
    4263         FragmentSearch.FragmentSet = new KeySet;
    4264         FragmentSearch.Root = FindAtom(RootKeyNr);
    4265         for (int i=AtomCount;i--;) {
    4266                 FragmentSearch.ShortestPathList[i] = -1;
    4267         }
    4268 
    4269         // Construct the complete KeySet which we need for topmost level only (but for all Roots)
    4270         atom *Walker = start;
    4271         KeySet CompleteMolecule;
    4272         while (Walker->next != end) {
    4273                 Walker = Walker->next;
    4274                 CompleteMolecule.insert(Walker->GetTrueFather()->nr);
    4275         }
    4276 
    4277         // this can easily be seen: if Order is 5, then the number of levels for each lower order is the total sum of the number of levels above, as
    4278         // each has to be split up. E.g. for the second level we have one from 5th, one from 4th, two from 3th (which in turn is one from 5th, one from 4th),
    4279         // hence we have overall four 2th order levels for splitting. This also allows for putting all into a single array (FragmentLowerOrdersList[])
    4280         // with the order along the cells as this: 5433222211111111 for BondOrder 5 needing 16=pow(2,5-1) cells (only we use bit-shifting which is faster)
    4281         RootNr = 0;      // counts through the roots in RootStack
    4282         while ((RootNr < UpgradeCount) && (!RootStack.empty())) {
    4283                 RootKeyNr = RootStack.front();
    4284                 RootStack.pop_front();
    4285                 Walker = FindAtom(RootKeyNr);
    4286                 // check cyclic lengths
    4287                 //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) {
    4288                 //      *out << Verbose(0) << "Bond order " << Walker->GetTrueFather()->AdaptiveOrder << " of Root " << *Walker << " greater than or equal to Minimum Ring size of " << MinimumRingSize << " found is not allowed." << endl;
    4289                 //} else
    4290                 {
    4291                         // increase adaptive order by one
    4292                         Walker->GetTrueFather()->AdaptiveOrder++;
    4293                         Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder;
    4294 
    4295                         // initialise Order-dependent entries of UniqueFragments structure
    4296                         FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList");
    4297                         FragmentSearch.BondsPerSPCount = (int *) Malloc(sizeof(int)*Order, "molecule::PowerSetGenerator: *BondsPerSPCount");
    4298                         for (int i=Order;i--;) {
    4299                                 FragmentSearch.BondsPerSPList[2*i] = new bond();                // start node
    4300                                 FragmentSearch.BondsPerSPList[2*i+1] = new bond();      // end node
    4301                                 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1];                // intertwine these two
    4302                                 FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i];
    4303                                 FragmentSearch.BondsPerSPCount[i] = 0;
    4304                         }
    4305 
    4306                         // allocate memory for all lower level orders in this 1D-array of ptrs
    4307                         NumLevels = 1 << (Order-1); // (int)pow(2,Order);
    4308                         FragmentLowerOrdersList[RootNr] = (Graph **) Malloc(sizeof(Graph *)*NumLevels, "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]");
    4309                         for (int i=0;i<NumLevels;i++)
    4310                                 FragmentLowerOrdersList[RootNr][i] = NULL;
    4311 
    4312                         // create top order where nothing is reduced
    4313                         *out << Verbose(0) << "==============================================================================================================" << endl;
    4314                         *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << "
    4315 
    4316                         // Create list of Graphs of current Bond Order (i.e. F_{ij})
    4317                         FragmentLowerOrdersList[RootNr][0] =    new Graph;
    4318                         FragmentSearch.TEFactor = 1.;
    4319                         FragmentSearch.Leaflet = FragmentLowerOrdersList[RootNr][0];                    // set to insertion graph
    4320                         FragmentSearch.Root = Walker;
    4321                         NumMoleculesOfOrder[RootNr] = PowerSetGenerator(out, Walker->AdaptiveOrder, FragmentSearch, CompleteMolecule);
    4322                         *out << Verbose(1) << "Number of resulting KeySets is: " << NumMoleculesOfOrder[RootNr] << "." << endl;
    4323                         if (NumMoleculesOfOrder[RootNr] != 0) {
    4324                                 NumMolecules = 0;
    4325 
    4326                                 // we don't have to dive into suborders! These keysets are all already created on lower orders!
    4327                                 // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed)
    4328 
    4329 //                              if ((NumLevels >> 1) > 0) {
    4330 //                                      // create lower order fragments
    4331 //                                      *out << Verbose(0) << "Creating list of unique fragments of lower Bond Order terms to be subtracted." << endl;
    4332 //                                      Order = Walker->AdaptiveOrder;
    4333 //                                      for (int source=0;source<(NumLevels >> 1);source++) { // 1-terms don't need any more splitting, that's why only half is gone through (shift again)
    4334 //                                              // step down to next order at (virtual) boundary of powers of 2 in array
    4335 //                                              while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order))
    4336 //                                                      Order--;
    4337 //                                              *out << Verbose(0) << "Current Order is: " << Order << "." << endl;
    4338 //                                              for (int SubOrder=Order-1;SubOrder>0;SubOrder--) {
    4339 //                                                      int dest = source + (1 << (Walker->AdaptiveOrder-(SubOrder+1)));
    4340 //                                                      *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl;
    4341 //                                                      *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl;
     4245  Graph ***FragmentLowerOrdersList = NULL;
     4246  int NumLevels, NumMolecules, TotalNumMolecules = 0, *NumMoleculesOfOrder = NULL;
     4247  int counter = 0, Order;
     4248  int UpgradeCount = RootStack.size();
     4249  KeyStack FragmentRootStack;
     4250  int RootKeyNr, RootNr;
     4251  struct UniqueFragments FragmentSearch;
     4252
     4253  *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl;
     4254
     4255  // FragmentLowerOrdersList is a 2D-array of pointer to MoleculeListClass objects, one dimension represents the ANOVA expansion of a single order (i.e. 5)
     4256  // with all needed lower orders that are subtracted, the other dimension is the BondOrder (i.e. from 1 to 5)
     4257  NumMoleculesOfOrder = (int *) Malloc(sizeof(int)*UpgradeCount, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder");
     4258  FragmentLowerOrdersList = (Graph ***) Malloc(sizeof(Graph **)*UpgradeCount, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList");
     4259
     4260  // initialise the fragments structure
     4261  FragmentSearch.ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::PowerSetGenerator: *ShortestPathList");
     4262  FragmentSearch.FragmentCounter = 0;
     4263  FragmentSearch.FragmentSet = new KeySet;
     4264  FragmentSearch.Root = FindAtom(RootKeyNr);
     4265  for (int i=AtomCount;i--;) {
     4266    FragmentSearch.ShortestPathList[i] = -1;
     4267  }
     4268
     4269  // Construct the complete KeySet which we need for topmost level only (but for all Roots)
     4270  atom *Walker = start;
     4271  KeySet CompleteMolecule;
     4272  while (Walker->next != end) {
     4273    Walker = Walker->next;
     4274    CompleteMolecule.insert(Walker->GetTrueFather()->nr);
     4275  }
     4276
     4277  // this can easily be seen: if Order is 5, then the number of levels for each lower order is the total sum of the number of levels above, as
     4278  // each has to be split up. E.g. for the second level we have one from 5th, one from 4th, two from 3th (which in turn is one from 5th, one from 4th),
     4279  // hence we have overall four 2th order levels for splitting. This also allows for putting all into a single array (FragmentLowerOrdersList[])
     4280  // with the order along the cells as this: 5433222211111111 for BondOrder 5 needing 16=pow(2,5-1) cells (only we use bit-shifting which is faster)
     4281  RootNr = 0;  // counts through the roots in RootStack
     4282  while ((RootNr < UpgradeCount) && (!RootStack.empty())) {
     4283    RootKeyNr = RootStack.front();
     4284    RootStack.pop_front();
     4285    Walker = FindAtom(RootKeyNr);
     4286    // check cyclic lengths
     4287    //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) {
     4288    //  *out << Verbose(0) << "Bond order " << Walker->GetTrueFather()->AdaptiveOrder << " of Root " << *Walker << " greater than or equal to Minimum Ring size of " << MinimumRingSize << " found is not allowed." << endl;
     4289    //} else
     4290    {
     4291      // increase adaptive order by one
     4292      Walker->GetTrueFather()->AdaptiveOrder++;
     4293      Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder;
     4294
     4295      // initialise Order-dependent entries of UniqueFragments structure
     4296      FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList");
     4297      FragmentSearch.BondsPerSPCount = (int *) Malloc(sizeof(int)*Order, "molecule::PowerSetGenerator: *BondsPerSPCount");
     4298      for (int i=Order;i--;) {
     4299        FragmentSearch.BondsPerSPList[2*i] = new bond();    // start node
     4300        FragmentSearch.BondsPerSPList[2*i+1] = new bond();  // end node
     4301        FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1];    // intertwine these two
     4302        FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i];
     4303        FragmentSearch.BondsPerSPCount[i] = 0;
     4304      }
     4305
     4306      // allocate memory for all lower level orders in this 1D-array of ptrs
     4307      NumLevels = 1 << (Order-1); // (int)pow(2,Order);
     4308      FragmentLowerOrdersList[RootNr] = (Graph **) Malloc(sizeof(Graph *)*NumLevels, "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]");
     4309      for (int i=0;i<NumLevels;i++)
     4310        FragmentLowerOrdersList[RootNr][i] = NULL;
     4311
     4312      // create top order where nothing is reduced
     4313      *out << Verbose(0) << "==============================================================================================================" << endl;
     4314      *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << "
     4315
     4316      // Create list of Graphs of current Bond Order (i.e. F_{ij})
     4317      FragmentLowerOrdersList[RootNr][0] =  new Graph;
     4318      FragmentSearch.TEFactor = 1.;
     4319      FragmentSearch.Leaflet = FragmentLowerOrdersList[RootNr][0];      // set to insertion graph
     4320      FragmentSearch.Root = Walker;
     4321      NumMoleculesOfOrder[RootNr] = PowerSetGenerator(out, Walker->AdaptiveOrder, FragmentSearch, CompleteMolecule);
     4322      *out << Verbose(1) << "Number of resulting KeySets is: " << NumMoleculesOfOrder[RootNr] << "." << endl;
     4323      if (NumMoleculesOfOrder[RootNr] != 0) {
     4324        NumMolecules = 0;
     4325
     4326        // we don't have to dive into suborders! These keysets are all already created on lower orders!
     4327        // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed)
     4328
     4329//        if ((NumLevels >> 1) > 0) {
     4330//          // create lower order fragments
     4331//          *out << Verbose(0) << "Creating list of unique fragments of lower Bond Order terms to be subtracted." << endl;
     4332//          Order = Walker->AdaptiveOrder;
     4333//          for (int source=0;source<(NumLevels >> 1);source++) { // 1-terms don't need any more splitting, that's why only half is gone through (shift again)
     4334//            // step down to next order at (virtual) boundary of powers of 2 in array
     4335//            while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order))
     4336//              Order--;
     4337//            *out << Verbose(0) << "Current Order is: " << Order << "." << endl;
     4338//            for (int SubOrder=Order-1;SubOrder>0;SubOrder--) {
     4339//              int dest = source + (1 << (Walker->AdaptiveOrder-(SubOrder+1)));
     4340//              *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl;
     4341//              *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl;
    43424342//
    4343 //                                                      // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules
    4344 //                                                      //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl;
    4345 //                                                      //NumMolecules = 0;
    4346 //                                                      FragmentLowerOrdersList[RootNr][dest] = new Graph;
    4347 //                                                      for(Graph::iterator runner = (*FragmentLowerOrdersList[RootNr][source]).begin();runner != (*FragmentLowerOrdersList[RootNr][source]).end(); runner++) {
    4348 //                                                              for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) {
    4349 //                                                                      Graph TempFragmentList;
    4350 //                                                                      FragmentSearch.TEFactor = -(*runner).second.second;
    4351 //                                                                      FragmentSearch.Leaflet = &TempFragmentList;                     // set to insertion graph
    4352 //                                                                      FragmentSearch.Root = FindAtom(*sprinter);
    4353 //                                                                      NumMoleculesOfOrder[RootNr] += PowerSetGenerator(out, SubOrder, FragmentSearch, (*runner).first);
    4354 //                                                                      // insert new keysets FragmentList into FragmentLowerOrdersList[Walker->AdaptiveOrder-1][dest]
    4355 //                                                                      *out << Verbose(1) << "Merging resulting key sets with those present in destination " << dest << "." << endl;
    4356 //                                                                      InsertGraphIntoGraph(out, *FragmentLowerOrdersList[RootNr][dest], TempFragmentList, &NumMolecules);
    4357 //                                                              }
    4358 //                                                      }
    4359 //                                                      *out << Verbose(1) << "Number of resulting molecules for SubOrder " << SubOrder << " is: " << NumMolecules << "." << endl;
    4360 //                                              }
    4361 //                                      }
    4362 //                              }
    4363                         } else {
    4364                                 Walker->GetTrueFather()->MaxOrder = true;
    4365 //                              *out << Verbose(1) << "Hence, we don't dive into SubOrders ... " << endl;
    4366                         }
    4367                         // now, we have completely filled each cell of FragmentLowerOrdersList[] for the current Walker->AdaptiveOrder
    4368                         //NumMoleculesOfOrder[Walker->AdaptiveOrder-1] = NumMolecules;
    4369                         TotalNumMolecules += NumMoleculesOfOrder[RootNr];
    4370 //                      *out << Verbose(1) << "Number of resulting molecules for Order " << (int)Walker->GetTrueFather()->AdaptiveOrder << " is: " << NumMoleculesOfOrder[RootNr] << "." << endl;
    4371                         RootStack.push_back(RootKeyNr); // put back on stack
    4372                         RootNr++;
    4373 
    4374                         // free Order-dependent entries of UniqueFragments structure for next loop cycle
    4375                         Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount");
    4376                         for (int i=Order;i--;) {
    4377                                 delete(FragmentSearch.BondsPerSPList[2*i]);
    4378                                 delete(FragmentSearch.BondsPerSPList[2*i+1]);
    4379                         }
    4380                         Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList");
    4381                 }
    4382         }
    4383         *out << Verbose(0) << "==============================================================================================================" << endl;
    4384         *out << Verbose(1) << "Total number of resulting molecules is: " << TotalNumMolecules << "." << endl;
    4385         *out << Verbose(0) << "==============================================================================================================" << endl;
    4386 
    4387         // cleanup FragmentSearch structure
    4388         Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList");
    4389         delete(FragmentSearch.FragmentSet);
    4390 
    4391         // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein)
    4392         // 5433222211111111
    4393         // 43221111
    4394         // 3211
    4395         // 21
    4396         // 1
    4397 
    4398         // Subsequently, we combine all into a single list (FragmentList)
    4399 
    4400         *out << Verbose(0) << "Combining the lists of all orders per order and finally into a single one." << endl;
    4401         if (FragmentList == NULL) {
    4402                 FragmentList = new Graph;
    4403                 counter = 0;
    4404         } else {
    4405                 counter = FragmentList->size();
    4406         }
    4407         RootNr = 0;
    4408         while (!RootStack.empty()) {
    4409                 RootKeyNr = RootStack.front();
    4410                 RootStack.pop_front();
    4411                 Walker = FindAtom(RootKeyNr);
    4412                 NumLevels = 1 << (Walker->AdaptiveOrder - 1);
    4413                 for(int i=0;i<NumLevels;i++) {
    4414                         if (FragmentLowerOrdersList[RootNr][i] != NULL) {
    4415                                 InsertGraphIntoGraph(out, *FragmentList, (*FragmentLowerOrdersList[RootNr][i]), &counter);
    4416                                 delete(FragmentLowerOrdersList[RootNr][i]);
    4417                         }
    4418                 }
    4419                 Free((void **)&FragmentLowerOrdersList[RootNr], "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]");
    4420                 RootNr++;
    4421         }
    4422         Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList");
    4423         Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder");
    4424 
    4425         *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl;
     4343//              // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules
     4344//              //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl;
     4345//              //NumMolecules = 0;
     4346//              FragmentLowerOrdersList[RootNr][dest] = new Graph;
     4347//              for(Graph::iterator runner = (*FragmentLowerOrdersList[RootNr][source]).begin();runner != (*FragmentLowerOrdersList[RootNr][source]).end(); runner++) {
     4348//                for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) {
     4349//                  Graph TempFragmentList;
     4350//                  FragmentSearch.TEFactor = -(*runner).second.second;
     4351//                  FragmentSearch.Leaflet = &TempFragmentList;      // set to insertion graph
     4352//                  FragmentSearch.Root = FindAtom(*sprinter);
     4353//                  NumMoleculesOfOrder[RootNr] += PowerSetGenerator(out, SubOrder, FragmentSearch, (*runner).first);
     4354//                  // insert new keysets FragmentList into FragmentLowerOrdersList[Walker->AdaptiveOrder-1][dest]
     4355//                  *out << Verbose(1) << "Merging resulting key sets with those present in destination " << dest << "." << endl;
     4356//                  InsertGraphIntoGraph(out, *FragmentLowerOrdersList[RootNr][dest], TempFragmentList, &NumMolecules);
     4357//                }
     4358//              }
     4359//              *out << Verbose(1) << "Number of resulting molecules for SubOrder " << SubOrder << " is: " << NumMolecules << "." << endl;
     4360//            }
     4361//          }
     4362//        }
     4363      } else {
     4364        Walker->GetTrueFather()->MaxOrder = true;
     4365//        *out << Verbose(1) << "Hence, we don't dive into SubOrders ... " << endl;
     4366      }
     4367      // now, we have completely filled each cell of FragmentLowerOrdersList[] for the current Walker->AdaptiveOrder
     4368      //NumMoleculesOfOrder[Walker->AdaptiveOrder-1] = NumMolecules;
     4369      TotalNumMolecules += NumMoleculesOfOrder[RootNr];
     4370//      *out << Verbose(1) << "Number of resulting molecules for Order " << (int)Walker->GetTrueFather()->AdaptiveOrder << " is: " << NumMoleculesOfOrder[RootNr] << "." << endl;
     4371      RootStack.push_back(RootKeyNr); // put back on stack
     4372      RootNr++;
     4373
     4374      // free Order-dependent entries of UniqueFragments structure for next loop cycle
     4375      Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount");
     4376      for (int i=Order;i--;) {
     4377        delete(FragmentSearch.BondsPerSPList[2*i]);
     4378        delete(FragmentSearch.BondsPerSPList[2*i+1]);
     4379      }
     4380      Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList");
     4381    }
     4382  }
     4383  *out << Verbose(0) << "==============================================================================================================" << endl;
     4384  *out << Verbose(1) << "Total number of resulting molecules is: " << TotalNumMolecules << "." << endl;
     4385  *out << Verbose(0) << "==============================================================================================================" << endl;
     4386
     4387  // cleanup FragmentSearch structure
     4388  Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList");
     4389  delete(FragmentSearch.FragmentSet);
     4390
     4391  // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein)
     4392  // 5433222211111111
     4393  // 43221111
     4394  // 3211
     4395  // 21
     4396  // 1
     4397
     4398  // Subsequently, we combine all into a single list (FragmentList)
     4399
     4400  *out << Verbose(0) << "Combining the lists of all orders per order and finally into a single one." << endl;
     4401  if (FragmentList == NULL) {
     4402    FragmentList = new Graph;
     4403    counter = 0;
     4404  } else {
     4405    counter = FragmentList->size();
     4406  }
     4407  RootNr = 0;
     4408  while (!RootStack.empty()) {
     4409    RootKeyNr = RootStack.front();
     4410    RootStack.pop_front();
     4411    Walker = FindAtom(RootKeyNr);
     4412    NumLevels = 1 << (Walker->AdaptiveOrder - 1);
     4413    for(int i=0;i<NumLevels;i++) {
     4414      if (FragmentLowerOrdersList[RootNr][i] != NULL) {
     4415        InsertGraphIntoGraph(out, *FragmentList, (*FragmentLowerOrdersList[RootNr][i]), &counter);
     4416        delete(FragmentLowerOrdersList[RootNr][i]);
     4417      }
     4418    }
     4419    Free((void **)&FragmentLowerOrdersList[RootNr], "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]");
     4420    RootNr++;
     4421  }
     4422  Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList");
     4423  Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder");
     4424
     4425  *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl;
    44264426};
    44274427
     
    44334433inline int CompareDoubles (const void * a, const void * b)
    44344434{
    4435         if (*(double *)a > *(double *)b)
    4436                 return -1;
    4437         else if (*(double *)a < *(double *)b)
    4438                 return 1;
    4439         else
    4440                 return 0;
     4435  if (*(double *)a > *(double *)b)
     4436    return -1;
     4437  else if (*(double *)a < *(double *)b)
     4438    return 1;
     4439  else
     4440    return 0;
    44414441};
    44424442
     
    44494449int * molecule::IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold)
    44504450{
    4451         int flag;
    4452         double *Distances = NULL, *OtherDistances = NULL;
    4453         Vector CenterOfGravity, OtherCenterOfGravity;
    4454         size_t *PermMap = NULL, *OtherPermMap = NULL;
    4455         int *PermutationMap = NULL;
    4456         atom *Walker = NULL;
    4457         bool result = true; // status of comparison
    4458 
    4459         *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl;
    4460         /// first count both their atoms and elements and update lists thereby ...
    4461         //*out << Verbose(0) << "Counting atoms, updating list" << endl;
    4462         CountAtoms(out);
    4463         OtherMolecule->CountAtoms(out);
    4464         CountElements();
    4465         OtherMolecule->CountElements();
    4466 
    4467         /// ... and compare:
    4468         /// -# AtomCount
    4469         if (result) {
    4470                 if (AtomCount != OtherMolecule->AtomCount) {
    4471                         *out << Verbose(4) << "AtomCounts don't match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl;
    4472                         result = false;
    4473                 } else *out << Verbose(4) << "AtomCounts match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl;
    4474         }
    4475         /// -# ElementCount
    4476         if (result) {
    4477                 if (ElementCount != OtherMolecule->ElementCount) {
    4478                         *out << Verbose(4) << "ElementCount don't match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;
    4479                         result = false;
    4480                 } else *out << Verbose(4) << "ElementCount match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;
    4481         }
    4482         /// -# ElementsInMolecule
    4483         if (result) {
    4484                 for (flag=MAX_ELEMENTS;flag--;) {
    4485                         //*out << Verbose(5) << "Element " <<   flag << ": " << ElementsInMolecule[flag] << " <-> " << OtherMolecule->ElementsInMolecule[flag] << "." << endl;
    4486                         if (ElementsInMolecule[flag] != OtherMolecule->ElementsInMolecule[flag])
    4487                                 break;
    4488                 }
    4489                 if (flag < MAX_ELEMENTS) {
    4490                         *out << Verbose(4) << "ElementsInMolecule don't match." << endl;
    4491                         result = false;
    4492                 } else *out << Verbose(4) << "ElementsInMolecule match." << endl;
    4493         }
    4494         /// then determine and compare center of gravity for each molecule ...
    4495         if (result) {
    4496                 *out << Verbose(5) << "Calculating Centers of Gravity" << endl;
    4497                 DetermineCenter(CenterOfGravity);
    4498                 OtherMolecule->DetermineCenter(OtherCenterOfGravity);
    4499                 *out << Verbose(5) << "Center of Gravity: ";
    4500                 CenterOfGravity.Output(out);
    4501                 *out << endl << Verbose(5) << "Other Center of Gravity: ";
    4502                 OtherCenterOfGravity.Output(out);
    4503                 *out << endl;
    4504                 if (CenterOfGravity.DistanceSquared(&OtherCenterOfGravity) > threshold*threshold) {
    4505                         *out << Verbose(4) << "Centers of gravity don't match." << endl;
    4506                         result = false;
    4507                 }
    4508         }
    4509 
    4510         /// ... then make a list with the euclidian distance to this center for each atom of both molecules
    4511         if (result) {
    4512                 *out << Verbose(5) << "Calculating distances" << endl;
    4513                 Distances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: Distances");
    4514                 OtherDistances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: OtherDistances");
    4515                 Walker = start;
    4516                 while (Walker->next != end) {
    4517                         Walker = Walker->next;
    4518                         Distances[Walker->nr] = CenterOfGravity.DistanceSquared(&Walker->x);
    4519                 }
    4520                 Walker = OtherMolecule->start;
    4521                 while (Walker->next != OtherMolecule->end) {
    4522                         Walker = Walker->next;
    4523                         OtherDistances[Walker->nr] = OtherCenterOfGravity.DistanceSquared(&Walker->x);
    4524                 }
    4525 
    4526                 /// ... sort each list (using heapsort (o(N log N)) from GSL)
    4527                 *out << Verbose(5) << "Sorting distances" << endl;
    4528                 PermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermMap");
    4529                 OtherPermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *OtherPermMap");
    4530                 gsl_heapsort_index (PermMap, Distances, AtomCount, sizeof(double), CompareDoubles);
    4531                 gsl_heapsort_index (OtherPermMap, OtherDistances, AtomCount, sizeof(double), CompareDoubles);
    4532                 PermutationMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermutationMap");
    4533                 *out << Verbose(5) << "Combining Permutation Maps" << endl;
    4534                 for(int i=AtomCount;i--;)
    4535                         PermutationMap[PermMap[i]] = (int) OtherPermMap[i];
    4536 
    4537                 /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all
    4538                 *out << Verbose(4) << "Comparing distances" << endl;
    4539                 flag = 0;
    4540                 for (int i=0;i<AtomCount;i++) {
    4541                         *out << Verbose(5) << "Distances squared: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " <<      threshold << endl;
    4542                         if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) > threshold*threshold)
    4543                                 flag = 1;
    4544                 }
    4545                 Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap");
    4546                 Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap");
    4547 
    4548                 /// free memory
    4549                 Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances");
    4550                 Free((void **)&OtherDistances, "molecule::IsEqualToWithinThreshold: OtherDistances");
    4551                 if (flag) { // if not equal
    4552                         Free((void **)&PermutationMap, "molecule::IsEqualToWithinThreshold: *PermutationMap");
    4553                         result = false;
    4554                 }
    4555         }
    4556         /// return pointer to map if all distances were below \a threshold
    4557         *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl;
    4558         if (result) {
    4559                 *out << Verbose(3) << "Result: Equal." << endl;
    4560                 return PermutationMap;
    4561         } else {
    4562                 *out << Verbose(3) << "Result: Not equal." << endl;
    4563                 return NULL;
    4564         }
     4451  int flag;
     4452  double *Distances = NULL, *OtherDistances = NULL;
     4453  Vector CenterOfGravity, OtherCenterOfGravity;
     4454  size_t *PermMap = NULL, *OtherPermMap = NULL;
     4455  int *PermutationMap = NULL;
     4456  atom *Walker = NULL;
     4457  bool result = true; // status of comparison
     4458
     4459  *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl;
     4460  /// first count both their atoms and elements and update lists thereby ...
     4461  //*out << Verbose(0) << "Counting atoms, updating list" << endl;
     4462  CountAtoms(out);
     4463  OtherMolecule->CountAtoms(out);
     4464  CountElements();
     4465  OtherMolecule->CountElements();
     4466
     4467  /// ... and compare:
     4468  /// -# AtomCount
     4469  if (result) {
     4470    if (AtomCount != OtherMolecule->AtomCount) {
     4471      *out << Verbose(4) << "AtomCounts don't match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl;
     4472      result = false;
     4473    } else *out << Verbose(4) << "AtomCounts match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl;
     4474  }
     4475  /// -# ElementCount
     4476  if (result) {
     4477    if (ElementCount != OtherMolecule->ElementCount) {
     4478      *out << Verbose(4) << "ElementCount don't match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;
     4479      result = false;
     4480    } else *out << Verbose(4) << "ElementCount match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;
     4481  }
     4482  /// -# ElementsInMolecule
     4483  if (result) {
     4484    for (flag=MAX_ELEMENTS;flag--;) {
     4485      //*out << Verbose(5) << "Element " <<  flag << ": " << ElementsInMolecule[flag] << " <-> " << OtherMolecule->ElementsInMolecule[flag] << "." << endl;
     4486      if (ElementsInMolecule[flag] != OtherMolecule->ElementsInMolecule[flag])
     4487        break;
     4488    }
     4489    if (flag < MAX_ELEMENTS) {
     4490      *out << Verbose(4) << "ElementsInMolecule don't match." << endl;
     4491      result = false;
     4492    } else *out << Verbose(4) << "ElementsInMolecule match." << endl;
     4493  }
     4494  /// then determine and compare center of gravity for each molecule ...
     4495  if (result) {
     4496    *out << Verbose(5) << "Calculating Centers of Gravity" << endl;
     4497    DetermineCenter(CenterOfGravity);
     4498    OtherMolecule->DetermineCenter(OtherCenterOfGravity);
     4499    *out << Verbose(5) << "Center of Gravity: ";
     4500    CenterOfGravity.Output(out);
     4501    *out << endl << Verbose(5) << "Other Center of Gravity: ";
     4502    OtherCenterOfGravity.Output(out);
     4503    *out << endl;
     4504    if (CenterOfGravity.DistanceSquared(&OtherCenterOfGravity) > threshold*threshold) {
     4505      *out << Verbose(4) << "Centers of gravity don't match." << endl;
     4506      result = false;
     4507    }
     4508  }
     4509
     4510  /// ... then make a list with the euclidian distance to this center for each atom of both molecules
     4511  if (result) {
     4512    *out << Verbose(5) << "Calculating distances" << endl;
     4513    Distances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: Distances");
     4514    OtherDistances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: OtherDistances");
     4515    Walker = start;
     4516    while (Walker->next != end) {
     4517      Walker = Walker->next;
     4518      Distances[Walker->nr] = CenterOfGravity.DistanceSquared(&Walker->x);
     4519    }
     4520    Walker = OtherMolecule->start;
     4521    while (Walker->next != OtherMolecule->end) {
     4522      Walker = Walker->next;
     4523      OtherDistances[Walker->nr] = OtherCenterOfGravity.DistanceSquared(&Walker->x);
     4524    }
     4525
     4526    /// ... sort each list (using heapsort (o(N log N)) from GSL)
     4527    *out << Verbose(5) << "Sorting distances" << endl;
     4528    PermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermMap");
     4529    OtherPermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *OtherPermMap");
     4530    gsl_heapsort_index (PermMap, Distances, AtomCount, sizeof(double), CompareDoubles);
     4531    gsl_heapsort_index (OtherPermMap, OtherDistances, AtomCount, sizeof(double), CompareDoubles);
     4532    PermutationMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermutationMap");
     4533    *out << Verbose(5) << "Combining Permutation Maps" << endl;
     4534    for(int i=AtomCount;i--;)
     4535      PermutationMap[PermMap[i]] = (int) OtherPermMap[i];
     4536
     4537    /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all
     4538    *out << Verbose(4) << "Comparing distances" << endl;
     4539    flag = 0;
     4540    for (int i=0;i<AtomCount;i++) {
     4541      *out << Verbose(5) << "Distances squared: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " <<  threshold << endl;
     4542      if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) > threshold*threshold)
     4543        flag = 1;
     4544    }
     4545    Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap");
     4546    Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap");
     4547
     4548    /// free memory
     4549    Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances");
     4550    Free((void **)&OtherDistances, "molecule::IsEqualToWithinThreshold: OtherDistances");
     4551    if (flag) { // if not equal
     4552      Free((void **)&PermutationMap, "molecule::IsEqualToWithinThreshold: *PermutationMap");
     4553      result = false;
     4554    }
     4555  }
     4556  /// return pointer to map if all distances were below \a threshold
     4557  *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl;
     4558  if (result) {
     4559    *out << Verbose(3) << "Result: Equal." << endl;
     4560    return PermutationMap;
     4561  } else {
     4562    *out << Verbose(3) << "Result: Not equal." << endl;
     4563    return NULL;
     4564  }
    45654565};
    45664566
     
    45744574int * molecule::GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule)
    45754575{
    4576         atom *Walker = NULL, *OtherWalker = NULL;
    4577         *out << Verbose(3) << "Begin of GetFatherAtomicMap." << endl;
    4578         int *AtomicMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::GetAtomicMap: *AtomicMap");   //Calloc
    4579         for (int i=AtomCount;i--;)
    4580                 AtomicMap[i] = -1;
    4581         if (OtherMolecule == this) {    // same molecule
    4582                 for (int i=AtomCount;i--;) // no need as -1 means already that there is trivial correspondence
    4583                         AtomicMap[i] = i;
    4584                 *out << Verbose(4) << "Map is trivial." << endl;
    4585         } else {
    4586                 *out << Verbose(4) << "Map is ";
    4587                 Walker = start;
    4588                 while (Walker->next != end) {
    4589                         Walker = Walker->next;
    4590                         if (Walker->father == NULL) {
    4591                                 AtomicMap[Walker->nr] = -2;
    4592                         } else {
    4593                                 OtherWalker = OtherMolecule->start;
    4594                                 while (OtherWalker->next != OtherMolecule->end) {
    4595                                         OtherWalker = OtherWalker->next;
    4596                         //for (int i=0;i<AtomCount;i++) { // search atom
    4597                                 //for (int j=0;j<OtherMolecule->AtomCount;j++) {
    4598                                         //*out << Verbose(4) << "Comparing father " << Walker->father << " with the other one " << OtherWalker->father << "." << endl;
    4599                                         if (Walker->father == OtherWalker)
    4600                                                 AtomicMap[Walker->nr] = OtherWalker->nr;
    4601                                 }
    4602                         }
    4603                         *out << AtomicMap[Walker->nr] << "\t";
    4604                 }
    4605                 *out << endl;
    4606         }
    4607         *out << Verbose(3) << "End of GetFatherAtomicMap." << endl;
    4608         return AtomicMap;
     4576  atom *Walker = NULL, *OtherWalker = NULL;
     4577  *out << Verbose(3) << "Begin of GetFatherAtomicMap." << endl;
     4578  int *AtomicMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::GetAtomicMap: *AtomicMap");  //Calloc
     4579  for (int i=AtomCount;i--;)
     4580    AtomicMap[i] = -1;
     4581  if (OtherMolecule == this) {  // same molecule
     4582    for (int i=AtomCount;i--;) // no need as -1 means already that there is trivial correspondence
     4583      AtomicMap[i] = i;
     4584    *out << Verbose(4) << "Map is trivial." << endl;
     4585  } else {
     4586    *out << Verbose(4) << "Map is ";
     4587    Walker = start;
     4588    while (Walker->next != end) {
     4589      Walker = Walker->next;
     4590      if (Walker->father == NULL) {
     4591        AtomicMap[Walker->nr] = -2;
     4592      } else {
     4593        OtherWalker = OtherMolecule->start;
     4594        while (OtherWalker->next != OtherMolecule->end) {
     4595          OtherWalker = OtherWalker->next;
     4596      //for (int i=0;i<AtomCount;i++) { // search atom
     4597        //for (int j=0;j<OtherMolecule->AtomCount;j++) {
     4598          //*out << Verbose(4) << "Comparing father " << Walker->father << " with the other one " << OtherWalker->father << "." << endl;
     4599          if (Walker->father == OtherWalker)
     4600            AtomicMap[Walker->nr] = OtherWalker->nr;
     4601        }
     4602      }
     4603      *out << AtomicMap[Walker->nr] << "\t";
     4604    }
     4605    *out << endl;
     4606  }
     4607  *out << Verbose(3) << "End of GetFatherAtomicMap." << endl;
     4608  return AtomicMap;
    46094609};
    46104610
     
    46204620bool molecule::OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output)
    46214621{
    4622         double temperature;
    4623         atom *Walker = NULL;
    4624         // test stream
    4625         if (output == NULL)
    4626                 return false;
    4627         else
    4628                 *output << "# Step Temperature [K] Temperature [a.u.]" << endl;
    4629         for (int step=startstep;step < endstep; step++) { // loop over all time steps
    4630                 temperature = 0.;
    4631                 Walker = start;
    4632                 while (Walker->next != end) {
    4633                         Walker = Walker->next;
    4634                         for (int i=NDIM;i--;)
    4635                                 temperature += Walker->type->mass * Trajectories[Walker].U.at(step).x[i]* Trajectories[Walker].U.at(step).x[i];
    4636                 }
    4637                 *output << step << "\t" << temperature*AtomicEnergyToKelvin << "\t" << temperature << endl;
    4638         }
    4639         return true;
    4640 };
     4622  double temperature;
     4623  atom *Walker = NULL;
     4624  // test stream
     4625  if (output == NULL)
     4626    return false;
     4627  else
     4628    *output << "# Step Temperature [K] Temperature [a.u.]" << endl;
     4629  for (int step=startstep;step < endstep; step++) { // loop over all time steps
     4630    temperature = 0.;
     4631    Walker = start;
     4632    while (Walker->next != end) {
     4633      Walker = Walker->next;
     4634      for (int i=NDIM;i--;)
     4635        temperature += Walker->type->mass * Trajectories[Walker].U.at(step).x[i]* Trajectories[Walker].U.at(step).x[i];
     4636    }
     4637    *output << step << "\t" << temperature*AtomicEnergyToKelvin << "\t" << temperature << endl;
     4638  }
     4639  return true;
     4640};
Note: See TracChangeset for help on using the changeset viewer.