Changeset 6ac7ee for src


Ignore:
Timestamp:
Feb 9, 2009, 5:24:10 PM (17 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, Candidate_v1.7.0, Candidate_v1.7.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:
d8b94a
Parents:
124df1
git-author:
Frederik Heber <heber@…> (02/09/09 15:55:37)
git-committer:
Frederik Heber <heber@…> (02/09/09 17:24:10)
Message:

Merge branch 'ConcaveHull' of ../espack2 into ConcaveHull

Conflicts:

molecuilder/src/boundary.cpp
molecuilder/src/boundary.hpp
molecuilder/src/builder.cpp
molecuilder/src/linkedcell.cpp
molecuilder/src/linkedcell.hpp
molecuilder/src/vector.cpp
molecuilder/src/vector.hpp
util/src/NanoCreator.c

Basically, this resulted from a lot of conversions two from spaces to one tab, which is my standard indentation. The mess was caused by eclipse auto-indenting. And in espack2:ConcaveHull was the new stuff, so all from ConcaveHull was replaced in case of doubt.
Additionally, vector had ofstream << operator instead ostream << ...

Location:
src
Files:
2 added
2 deleted
34 edited

Legend:

Unmodified
Added
Removed
  • src/Hbondangle.db

    • Property mode changed from 100644 to 100755
  • src/Hbonddistance.db

    • Property mode changed from 100644 to 100755
  • src/Makefile.am

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    1 SOURCE = atom.cpp bond.cpp boundary.cpp builder.cpp config.cpp element.cpp helpers.cpp molecules.cpp moleculelist.cpp parser.cpp periodentafel.cpp vector.cpp verbose.cpp
    2 HEADER = boundary.hpp defs.hpp helpers.hpp molecules.hpp parser.hpp periodentafel.hpp stackclass.hpp vector.hpp
     1SOURCE = atom.cpp bond.cpp boundary.cpp builder.cpp config.cpp element.cpp ellipsoid.cpp helpers.cpp molecules.cpp linkedcell.cpp moleculelist.cpp parser.cpp periodentafel.cpp vector.cpp verbose.cpp
     2HEADER = boundary.hpp defs.hpp ellipsoid.hpp helpers.hpp linkedcell.hpp molecules.hpp parser.hpp periodentafel.hpp stackclass.hpp vector.hpp
    33
    44bin_PROGRAMS = molecuilder joiner analyzer
    55molecuilderdir = ${bindir}
    6 molecuilder_DATA = elements.db valence.db       orbitals.db Hbonddistance.db Hbondangle.db
     6molecuilder_DATA = elements.db valence.db orbitals.db Hbonddistance.db Hbondangle.db
    77molecuilder_SOURCES =  ${SOURCE} ${HEADER}
    88joiner_SOURCES = joiner.cpp datacreator.cpp element.cpp helpers.cpp periodentafel.cpp parser.cpp verbose.cpp datacreator.hpp helpers.hpp parser.hpp periodentafel.hpp
  • src/analyzer.cpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    33 * Takes evaluated fragments (energy and forces) and does evaluation of how sensible the BOSSANOVA
    44 * approach was, e.g. in the decay of the many-body-contributions.
    5  *   
     5 *
    66 */
    77
     
    99
    1010#include "datacreator.hpp"
    11 #include "helpers.hpp" 
     11#include "helpers.hpp"
    1212#include "parser.hpp"
    13 #include "periodentafel.hpp" 
     13#include "periodentafel.hpp"
    1414
    1515// include config.h
     
    2323int main(int argc, char **argv)
    2424{
    25   periodentafel *periode = NULL; // and a period table of all elements
    26   EnergyMatrix Energy;
    27   EnergyMatrix Hcorrection;
    28   ForceMatrix Force;
    29   ForceMatrix Shielding;
    30   ForceMatrix ShieldingPAS;
    31   EnergyMatrix Time;
    32   EnergyMatrix EnergyFragments;
    33   EnergyMatrix HcorrectionFragments;
    34   ForceMatrix ForceFragments;
    35   ForceMatrix ShieldingFragments;
    36   ForceMatrix ShieldingPASFragments;
    37   KeySetsContainer KeySet;
    38   ofstream output;
    39   ofstream output2;
    40   ofstream output3;
    41   ofstream output4;
    42   ifstream input;
    43   stringstream filename;
    44   time_t t = time(NULL);
    45   struct tm *ts = localtime(&t);
    46   char *datum = asctime(ts);
    47   stringstream Orderxrange;
    48   stringstream Fragmentxrange;
    49   stringstream yrange;
    50   char *dir = NULL;
    51   bool Hcorrected = true;
    52   double norm;
    53   int counter;
    54  
    55   cout << "ANOVA Analyzer" << endl;
    56   cout << "==============" << endl;
    57  
    58   // Get the command line options
    59   if (argc < 4) {
    60     cout << "Usage: " << argv[0] << " <inputdir> <prefix> <outputdir> [elementsdb]" << endl;
    61     cout << "<inputdir>\ttherein the output of a molecuilder fragmentation is expected, each fragment with a subdir containing an energy.all and a forces.all file." << endl;
    62     cout << "<prefix>\tprefix of energy and forces file." << endl;
    63     cout << "<outputdir>\tcreated plotfiles and datafiles are placed into this directory " << endl;
    64     cout << "[elementsdb]\tpath to elements database, needed for shieldings." << endl;
    65     return 1;
    66   } else {
    67     dir = (char *) Malloc(sizeof(char)*(strlen(argv[2])+2), "main: *dir");
    68     strcpy(dir, "/");
    69     strcat(dir, argv[2]);
    70   }
    71  
    72   if (argc > 4) {
    73     cout << "Loading periodentafel." << endl;
    74     periode = new periodentafel;
    75     periode->LoadPeriodentafel(argv[4]);
    76   }
    77  
    78   // Test the given directory
    79   if (!TestParams(argc, argv))
    80     return 1;
    81 
    82   // +++++++++++++++++ PARSING +++++++++++++++++++++++++++++++
    83  
    84   // ------------- Parse through all Fragment subdirs --------
    85   if (!Energy.ParseFragmentMatrix(argv[1], dir, EnergySuffix,0,0)) return 1;
    86   Hcorrected = Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX,0,0);
    87   if (!Force.ParseFragmentMatrix(argv[1], dir, ForcesSuffix,0,0)) return 1;
    88   if (!Time.ParseFragmentMatrix(argv[1], dir, TimeSuffix, 10,1)) return 1;
    89   if (periode != NULL) { // also look for PAS values
    90     if (!Shielding.ParseFragmentMatrix(argv[1], dir, ShieldingSuffix, 1, 0)) return 1;
    91     if (!ShieldingPAS.ParseFragmentMatrix(argv[1], dir, ShieldingPASSuffix, 1, 0)) return 1;
    92   }
    93 
    94   // ---------- Parse the TE Factors into an array -----------------
    95   if (!Energy.ParseIndices()) return 1;
    96   if (Hcorrected) Hcorrection.ParseIndices();
    97  
    98   // ---------- Parse the Force indices into an array ---------------
    99   if (!Force.ParseIndices(argv[1])) return 1;
    100   if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return 1;
    101   if (!ForceFragments.ParseIndices(argv[1])) return 1;
    102 
    103   // ---------- Parse the shielding indices into an array ---------------
    104   if (periode != NULL) { // also look for PAS values
    105     if(!Shielding.ParseIndices(argv[1])) return 1;
    106     if(!ShieldingPAS.ParseIndices(argv[1])) return 1;
    107     if (!ShieldingFragments.AllocateMatrix(Shielding.Header, Shielding.MatrixCounter, Shielding.RowCounter, Shielding.ColumnCounter)) return 1;
    108     if (!ShieldingPASFragments.AllocateMatrix(ShieldingPAS.Header, ShieldingPAS.MatrixCounter, ShieldingPAS.RowCounter, ShieldingPAS.ColumnCounter)) return 1;
    109     if(!ShieldingFragments.ParseIndices(argv[1])) return 1;
    110     if(!ShieldingPASFragments.ParseIndices(argv[1])) return 1;
    111   }
    112 
    113   // ---------- Parse the KeySets into an array ---------------
    114   if (!KeySet.ParseKeySets(argv[1], Force.RowCounter, Force.MatrixCounter)) return 1;
    115   if (!KeySet.ParseManyBodyTerms()) return 1;
    116  
    117   // ---------- Parse fragment files created by 'joiner' into an array -------------
    118   if (!EnergyFragments.ParseFragmentMatrix(argv[1], dir, EnergyFragmentSuffix,0,0)) return 1;
    119   if (Hcorrected) HcorrectionFragments.ParseFragmentMatrix(argv[1], dir, HcorrectionFragmentSuffix,0,0);
    120   if (!ForceFragments.ParseFragmentMatrix(argv[1], dir, ForceFragmentSuffix,0,0)) return 1;
    121   if (periode != NULL) { // also look for PAS values
    122     if (!ShieldingFragments.ParseFragmentMatrix(argv[1], dir, ShieldingFragmentSuffix, 1, 0)) return 1;
    123     if (!ShieldingPASFragments.ParseFragmentMatrix(argv[1], dir, ShieldingPASFragmentSuffix, 1, 0)) return 1;
    124   }
    125 
    126   // +++++++++++++++ TESTING ++++++++++++++++++++++++++++++
    127  
    128   // print energy and forces to file
    129   filename.str("");
    130   filename << argv[3] << "/" << "energy-forces.all";
    131   output.open(filename.str().c_str(), ios::out);
    132   output << endl << "Total Energy" << endl << "==============" << endl << Energy.Header << endl;
    133   for(int j=0;j<Energy.RowCounter[Energy.MatrixCounter];j++) {
    134     for(int k=0;k<Energy.ColumnCounter;k++)
    135       output << scientific << Energy.Matrix[ Energy.MatrixCounter ][j][k] << "\t";
    136     output << endl;
    137   }
    138   output << endl;
    139  
    140   output << endl << "Total Forces" << endl << "===============" << endl << Force.Header << endl;
    141   for(int j=0;j<Force.RowCounter[Force.MatrixCounter];j++) {
    142     for(int k=0;k<Force.ColumnCounter;k++)
    143       output << scientific << Force.Matrix[ Force.MatrixCounter ][j][k] << "\t";
    144     output << endl;
    145   }
    146   output << endl;
    147 
    148   if (periode != NULL) { // also look for PAS values
    149     output << endl << "Total Shieldings" << endl << "===============" << endl << Shielding.Header << endl;
    150     for(int j=0;j<Shielding.RowCounter[Shielding.MatrixCounter];j++) {
    151       for(int k=0;k<Shielding.ColumnCounter;k++)
    152         output << scientific << Shielding.Matrix[ Shielding.MatrixCounter ][j][k] << "\t";
    153       output << endl;
    154     }
    155     output << endl;
    156  
    157     output << endl << "Total Shieldings PAS" << endl << "===============" << endl << ShieldingPAS.Header << endl;
    158     for(int j=0;j<ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter];j++) {
    159       for(int k=0;k<ShieldingPAS.ColumnCounter;k++)
    160         output << scientific << ShieldingPAS.Matrix[ ShieldingPAS.MatrixCounter ][j][k] << "\t";
    161       output << endl;
    162     }
    163     output << endl;
    164   }
    165  
    166   output << endl << "Total Times" << endl << "===============" << endl << Time.Header << endl;
    167   for(int j=0;j<Time.RowCounter[Time.MatrixCounter];j++) {
    168     for(int k=0;k<Time.ColumnCounter;k++) {
    169       output << scientific << Time.Matrix[ Time.MatrixCounter ][j][k] << "\t";
    170     }
    171     output << endl;
    172   }
    173   output << endl;
    174   output.close();
    175   for(int k=0;k<Time.ColumnCounter;k++)
    176     Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k] = Time.Matrix[ Time.MatrixCounter ][Time.RowCounter[Time.MatrixCounter]-1][k];
    177 
    178   // +++++++++++++++ ANALYZING ++++++++++++++++++++++++++++++
    179  
    180   cout << "Analyzing ..." << endl;
    181 
    182   // ======================================= Creating the data files ==============================================================
    183 
    184   // +++++++++++++++++++++++++++++++++++++++ Plotting Simtime vs Bond Order
    185   // +++++++++++++++++++++++++++++++++++++++ Plotting Delta Simtime vs Bond Order
    186   if (!OpenOutputFile(output, argv[3], "SimTime-Order.dat" )) return false;
    187   if (!OpenOutputFile(output2, argv[3], "DeltaSimTime-Order.dat" )) return false;
    188   for(int j=Time.RowCounter[Time.MatrixCounter];j--;)
    189     for(int k=Time.ColumnCounter;k--;) {
    190       Time.Matrix[ Time.MatrixCounter ][j][k] = 0.;
    191     }
    192   counter = 0;
    193   output << "#Order\tFrag.No.\t" << Time.Header << endl;
    194   output2 << "#Order\tFrag.No.\t" << Time.Header << endl;
    195   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
    196     for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;)
    197       for(int j=Time.RowCounter[Time.MatrixCounter];j--;)
    198         for(int k=Time.ColumnCounter;k--;) {
    199           Time.Matrix[ Time.MatrixCounter ][j][k] += Time.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
    200         }
    201     counter += KeySet.FragmentsPerOrder[BondOrder];
    202     output << BondOrder+1 << "\t" << counter;
    203     output2 << BondOrder+1 << "\t" << counter;
    204     for(int k=0;k<Time.ColumnCounter;k++) {
    205       output << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k];
    206       if (fabs(Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k]) > MYEPSILON)
    207         output2 << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k] / Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k];
    208       else
    209         output2 << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k];
    210     }
    211     output << endl;
    212     output2 << endl;
    213   }
    214   output.close();
    215   output2.close();
    216 
    217   // +++++++++++++++++++++++++++++++++++++++ Plotting shieldings
    218 
    219   if (periode != NULL) { // also look for PAS values
    220     if (!CreateDataDeltaForcesOrderPerAtom(ShieldingPAS, ShieldingPASFragments, KeySet, argv[3], "DeltaShieldingsPAS-Order", "Plot of error between approximated shieldings and full shieldings versus the Bond Order", datum)) return 1;
    221     if (!CreateDataForcesOrderPerAtom(ShieldingPASFragments, KeySet, argv[3], "ShieldingsPAS-Order", "Plot of approximated shieldings versus the Bond Order", datum)) return 1;
    222     if (!AppendOutputFile(output, argv[3], "ShieldingsPAS-Order.dat" )) return false;
    223     output << endl << "# Full" << endl;
    224     for(int j=0;j<ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter];j++) {
    225       output << j << "\t";
    226       for(int k=0;k<ShieldingPAS.ColumnCounter;k++)
    227         output << scientific <<  ShieldingPAS.Matrix[ ShieldingPAS.MatrixCounter ][j][k] << "\t"; //*(((k>1) && (k<6))? 1.e6 : 1.) << "\t";
    228       output << endl;
    229     }
    230   }
    231   output.close();
    232 
    233  
    234   // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in energy to full QM
    235   if (!CreateDataDeltaEnergyOrder(Energy, EnergyFragments, KeySet, argv[3], "DeltaEnergies-Order", "Plot of error between approximated and full energies energies versus the Bond Order", datum)) return 1;
    236  
    237   // +++++++++++++++++++++++++++++++++++Plotting Energies vs. Order
    238   if (!CreateDataEnergyOrder(EnergyFragments, KeySet, argv[3], "Energies-Order", "Plot of approximated energies versus the Bond Order", datum)) return 1;
    239  
    240   // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in forces to full QM
    241   if (!CreateDataDeltaForcesOrderPerAtom(Force, ForceFragments, KeySet, argv[3], "DeltaForces-Order", "Plot of error between approximated forces and full forces versus the Bond Order", datum)) return 1;
    242 
    243   // min force
    244   if (!CreateDataDeltaForcesOrder(Force, ForceFragments, KeySet, argv[3], "DeltaMinForces-Order", "Plot of min error between approximated forces and full forces versus the Bond Order", datum, CreateMinimumForce)) return 1;
    245 
    246   // mean force
    247   if (!CreateDataDeltaForcesOrder(Force, ForceFragments, KeySet, argv[3], "DeltaMeanForces-Order", "Plot of mean error between approximated forces and full forces versus the Bond Order", datum, CreateMeanForce)) return 1;
    248 
    249   // max force
    250   if (!CreateDataDeltaForcesOrder(Force, ForceFragments, KeySet, argv[3], "DeltaMaxForces-Order", "Plot of max error between approximated forces and full forces versus the Bond Order", datum, CreateMaximumForce)) return 1;
    251 
    252   // ++++++++++++++++++++++++++++++++++++++Plotting Forces vs. Order
    253   if (!CreateDataForcesOrderPerAtom(ForceFragments, KeySet, argv[3], "Forces-Order", "Plot of approximated forces versus the Bond Order", datum)) return 1;
    254   if (!AppendOutputFile(output, argv[3], "Forces-Order.dat" )) return false;
    255   output << endl << "# Full" << endl;
    256   for(int j=0;j<Force.RowCounter[Force.MatrixCounter];j++) {
    257     output << j << "\t";
    258     for(int k=0;k<Force.ColumnCounter;k++)
    259       output << scientific <<  Force.Matrix[ Force.MatrixCounter ][j][k] << "\t";
    260     output << endl;
    261   }
    262   output.close();
    263   // min force
    264   if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MinForces-Order", "Plot of min approximated forces versus the Bond Order", datum, CreateMinimumForce)) return 1;
    265 
    266   // mean force
    267   if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MeanForces-Order", "Plot of mean approximated forces versus the Bond Order", datum, CreateMeanForce)) return 1;
    268 
    269   // max force
    270   if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MaxForces-Order", "Plot of max approximated forces versus the Bond Order", datum, CreateMaximumForce)) return 1;
    271 
    272   // ++++++++++++++++++++++++++++++++++++++Plotting vector sum (should be 0) vs. bond order
    273   if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "VectorSum-Order", "Plot of vector sum of the approximated forces versus the Bond Order", datum, CreateVectorSumForce)) return 1;
    274 
    275   // +++++++++++++++++++++++++++++++Plotting energyfragments vs. order
    276   if (!CreateDataFragment(EnergyFragments, KeySet, argv[3], "Energies-Fragment", "Plot of fragment energy versus the Fragment No", datum, CreateEnergy)) return 1;
    277   if (!CreateDataFragment(EnergyFragments, KeySet, argv[3], "Energies-FragmentOrder", "Plot of fragment energy of each Fragment No vs. Bond Order", datum, CreateEnergy)) return 1;
    278   if (!CreateDataFragmentOrder(EnergyFragments, KeySet, argv[3], "MaxEnergies-FragmentOrder", "Plot of maximum of fragment energy vs. Bond Order", datum, CreateMaxFragmentOrder)) return 1;
    279   if (!CreateDataFragmentOrder(EnergyFragments, KeySet, argv[3], "MinEnergies-FragmentOrder", "Plot of minimum of fragment energy vs. Bond Order", datum, CreateMinFragmentOrder)) return 1;
    280 
    281   // +++++++++++++++++++++++++++++++Ploting min/mean/max forces for each fragment
    282   // min force
    283   if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MinForces-Fragment", "Plot of min approximated forces versus the Fragment No", datum, CreateMinimumForce)) return 1;
    284 
    285   // mean force
    286   if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MeanForces-Fragment", "Plot of mean approximated forces versus the Fragment No", datum, CreateMeanForce)) return 1;
    287 
    288   // max force
    289   if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MaxForces-Fragment", "Plot of max approximated forces versus the Fragment No", datum, CreateMaximumForce)) return 1;
    290 
    291   // +++++++++++++++++++++++++++++++Ploting min/mean/max forces for each fragment per order
    292   // min force
    293   if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MinForces-FragmentOrder", "Plot of min approximated forces of each Fragment No vs. Bond Order", datum, CreateMinimumForce)) return 1;
    294 
    295   // mean force
    296   if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MeanForces-FragmentOrder", "Plot of mean approximated forces of each Fragment No vs. Bond Order", datum, CreateMeanForce)) return 1;
    297 
    298   // max force
    299   if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MaxForces-FragmentOrder", "Plot of max approximated forces of each Fragment No vs. Bond Order", datum, CreateMaximumForce)) return 1;
    300 
    301   // ======================================= Creating the plot files ==============================================================
    302  
    303   Orderxrange << "[1:" << KeySet.Order << "]";
    304   Fragmentxrange << "[0:" << KeySet.FragmentCounter+1 << "]";
    305   yrange.str("[1e-8:1e+1]");
    306  
    307   // +++++++++++++++++++++++++++++++++++++++ Plotting Simtime vs Bond Order
    308   if (!CreatePlotOrder(Time, KeySet, argv[3], "SimTime-Order", 1, "below", "y", "",  1, 1, "bond order k", "Evaluation time [s]", Orderxrange.str().c_str(), "", "1" , "with linespoints", EnergyPlotLine)) return 1;
    309  
    310   // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in energy to full QM
    311   if (!CreatePlotOrder(Energy, KeySet, argv[3], "DeltaEnergies-Order", 1, "outside", "y", "",  1, 1, "bond order k", "absolute error in energy [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsEnergyPlotLine)) return 1;
    312  
    313   // +++++++++++++++++++++++++++++++++++Plotting Energies vs. Order
    314   if (!CreatePlotOrder(Energy, KeySet, argv[3], "Energies-Order", 1, "outside", "", "",  1, 1, "bond order k", "approximate energy [Ht]", Orderxrange.str().c_str(), "", "1" , "with linespoints", EnergyPlotLine)) return 1;
    315 
    316   // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in forces to full QM
    317   yrange.str("[1e-8:1e+0]");
    318   // min force
    319   if (!CreatePlotOrder(Force, KeySet, argv[3], "DeltaMinForces-Order", 2, "top right", "y", "",  1, 1, "bond order k", "absolute error in min force [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;
    320 
    321   // mean force
    322   if (!CreatePlotOrder(Force, KeySet, argv[3], "DeltaMeanForces-Order", 2, "top right", "y", "",  1, 1, "bond order k", "absolute error in mean force [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsFirstForceValuePlotLine)) return 1;
    323 
    324   // max force
    325   if (!CreatePlotOrder(Force, KeySet, argv[3], "DeltaMaxForces-Order", 2, "top right", "y", "",  1, 1, "bond order k", "absolute error in max force [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;
    326 
    327   // min/mean/max comparison for total force
    328   if(!OpenOutputFile(output, argv[3], "DeltaMinMeanMaxTotalForce-Order.pyx")) return 1;
    329   CreatePlotHeader(output, "DeltaMinMeanMaxTotalForce-Order", 1, "bottom left", "y", NULL,  1, 1, "bond order k", "absolute error in total forces [Ht/a.u.]");
    330   output << "plot " << Orderxrange.str().c_str() << " [1e-8:1e+0] \\" << endl; 
    331   output << "'DeltaMinForces-Order.dat' title 'minimum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints, \\" << endl;
    332   output << "'DeltaMeanForces-Order.dat' title 'mean' using 1:(abs($" << 8 << ")) with linespoints, \\" << endl;
    333   output << "'DeltaMaxForces-Order.dat' title 'maximum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints" << endl;
    334   output.close(); 
    335 
    336   // ++++++++++++++++++++++++++++++++++++++Plotting Forces vs. Order
    337   // min force
    338   if (!CreatePlotOrder(Force, KeySet, argv[3], "MinForces-Order", 2, "bottom right", "y", "",  1, 1, "bond order k", "absolute approximated min force [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;
    339 
    340   // mean force
    341   if (!CreatePlotOrder(Force, KeySet, argv[3], "MeanForces-Order", 2, "bottom right", "y", "",  1, 1, "bond order k", "absolute approximated mean force [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", AbsFirstForceValuePlotLine)) return 1;
    342 
    343   // max force
    344   if (!CreatePlotOrder(Force, KeySet, argv[3], "MaxForces-Order", 2, "bottom right", "y", "",  1, 1, "bond order k", "absolute approximated max force [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;
    345 
    346   // min/mean/max comparison for total force
    347   if(!OpenOutputFile(output, argv[3],"MinMeanMaxTotalForce-Order.pyx")) return 1;
    348   CreatePlotHeader(output, "MinMeanMaxTotalForce-Order", 1, "bottom left", "y", NULL, 1, 1, "bond order k", "absolute total force [Ht/a.u.]");
    349   output << "plot "<< Orderxrange.str().c_str() << " [1e-8:1e+0] \\" << endl; 
    350   output << "'MinForces-Order.dat' title 'minimum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints, \\" << endl;
    351   output << "'MeanForces-Order.dat' title 'mean' using 1:(abs($" << 8 << ")) with linespoints, \\" << endl;
    352   output << "'MaxForces-Order.dat' title 'maximum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints" << endl;
    353   output.close(); 
    354 
    355   // ++++++++++++++++++++++++++++++++++++++Plotting vector sum vs. Order
    356 
    357   if (!CreatePlotOrder(Force, KeySet, argv[3], "VectorSum-Order", 2, "bottom right", "y" ,"", 1, 1, "bond order k", "vector sum of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;
    358 
    359   // +++++++++++++++++++++++++++++++Plotting energyfragments vs. order
    360   yrange.str("");
    361   yrange << "[" << EnergyFragments.FindMinValue() << ":" << EnergyFragments.FindMaxValue() << "]";
    362   if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "Energies-Fragment", 5, "below", "y", "", 1, 5, "fragment number", "Energies of each fragment [Ht]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with points", AbsEnergyPlotLine)) return 1;
    363   if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "Energies-FragmentOrder", 5, "below", "y", "", 1, 1, "bond order", "Energies of each fragment [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with points", AbsEnergyPlotLine)) return 1;
    364   if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "MaxEnergies-FragmentOrder", 5, "below", "y", "", 1, 1, "bond order", "Maximum fragment energy [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsEnergyPlotLine)) return 1;
    365   if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "MinEnergies-FragmentOrder", 5, "below", "y", "", 1, 1, "bond order", "Minimum fragment energy [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsEnergyPlotLine)) return 1;
    366 
    367   // +++++++++++++++++++++++++++++++=Ploting min/mean/max forces for each fragment
    368   yrange.str("");
    369   yrange << "[" << ForceFragments.FindMinValue() << ":" << ForceFragments.FindMaxValue()<< "]";
    370   // min
    371   if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MinForces-Fragment", 5, "below", "y", "set boxwidth 0.2", 1, 5, "fragment number", "minimum of approximated forces [Ht/a.u.]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with boxes fillcolor", BoxesForcePlotLine)) return 1;
    372    
    373   // mean
    374   if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MeanForces-Fragment", 5, "below", "y", "set boxwidth 0.2", 1, 5, "fragment number", "mean of approximated forces [Ht/a.u.]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with boxes fillcolor", BoxesFirstForceValuePlotLine)) return 1;
    375    
    376   // max
    377   if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MaxForces-Fragment", 5, "below", "y", "set boxwidth 0.2", 1, 5, "fragment number", "maximum of approximated forces [Ht/a.u.]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with boxes fillcolor", BoxesForcePlotLine)) return 1;
    378 
    379   // +++++++++++++++++++++++++++++++=Ploting min/mean/max forces for each fragment per bond order
    380   // min
    381   if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MinForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "minimum of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesForcePlotLine)) return 1;
    382    
    383   // mean
    384   if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MeanForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "mean of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesFirstForceValuePlotLine)) return 1;
    385    
    386   // max
    387   if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MaxForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "maximum of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesForcePlotLine)) return 1;
    388  
    389   // +++++++++++++++++++++++++++++++=Ploting approximated and true shielding for each atom
    390   if (periode != NULL) { // also look for PAS values
    391     if(!OpenOutputFile(output, argv[3], "ShieldingsPAS-Order.pyx")) return 1;
    392     if(!OpenOutputFile(output2, argv[3], "DeltaShieldingsPAS-Order.pyx")) return 1;
    393     CreatePlotHeader(output, "ShieldingsPAS-Order", 1, "top right", NULL, NULL,  1, 5, "nuclei index", "iso chemical shielding value [ppm]");
    394     CreatePlotHeader(output2, "DeltaShieldingsPAS-Order", 1, "top right", NULL, NULL,  1, 5, "nuclei index", "iso chemical shielding value [ppm]");
    395     double step=0.8/KeySet.Order;
    396     output << "set boxwidth " << step << endl;
    397     output << "plot [0:" << ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter]+10 << "]\\" << endl;
    398     output2 << "plot [0:" << ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter]+10 << "]\\" << endl;
    399     for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
    400       output << "'ShieldingsPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1+" << step*(double)BondOrder << "):7 with boxes, \\" << endl;
    401       output2 << "'DeltaShieldingsPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1):7 with linespoints";
    402       if (BondOrder-1 != KeySet.Order)
    403         output2 << ", \\" << endl;
    404     }
    405     output << "'ShieldingsPAS-Order.dat' index " << KeySet.Order << " title 'Full' using ($1+" << step*(double)KeySet.Order << "):7 with boxes" << endl;
    406     output.close(); 
    407     output2.close(); 
    408   }
    409 
    410   // create Makefile
    411   if(!OpenOutputFile(output, argv[3], "Makefile")) return 1;
    412   output << "PYX = $(shell ls *.pyx)" << endl << endl;
    413   output << "EPS = $(PYX:.pyx=.eps)" << endl << endl;
    414   output << "%.eps: %.pyx" << endl;
    415   output << "\t~/build/pyxplot/pyxplot $<" << endl << endl;
    416   output << "all: $(EPS)" << endl << endl;
    417   output << ".PHONY: clean" << endl;
    418   output << "clean:" << endl;
    419   output << "\trm -rf $(EPS)" << endl;
    420   output.close();
    421  
    422   // ++++++++++++++++ exit ++++++++++++++++++++++++++++++++++
    423   delete(periode);
    424   Free((void **)&dir, "main: *dir");
    425   cout << "done." << endl;
    426   return 0;
     25        periodentafel *periode = NULL; // and a period table of all elements
     26        EnergyMatrix Energy;
     27        EnergyMatrix Hcorrection;
     28        ForceMatrix Force;
     29        ForceMatrix Shielding;
     30        ForceMatrix ShieldingPAS;
     31        EnergyMatrix Time;
     32        EnergyMatrix EnergyFragments;
     33        EnergyMatrix HcorrectionFragments;
     34        ForceMatrix ForceFragments;
     35        ForceMatrix ShieldingFragments;
     36        ForceMatrix ShieldingPASFragments;
     37        KeySetsContainer KeySet;
     38        ofstream output;
     39        ofstream output2;
     40        ofstream output3;
     41        ofstream output4;
     42        ifstream input;
     43        stringstream filename;
     44        time_t t = time(NULL);
     45        struct tm *ts = localtime(&t);
     46        char *datum = asctime(ts);
     47        stringstream Orderxrange;
     48        stringstream Fragmentxrange;
     49        stringstream yrange;
     50        char *dir = NULL;
     51        bool Hcorrected = true;
     52        double norm;
     53        int counter;
     54
     55        cout << "ANOVA Analyzer" << endl;
     56        cout << "==============" << endl;
     57
     58        // Get the command line options
     59        if (argc < 4) {
     60                cout << "Usage: " << argv[0] << " <inputdir> <prefix> <outputdir> [elementsdb]" << endl;
     61                cout << "<inputdir>\ttherein the output of a molecuilder fragmentation is expected, each fragment with a subdir containing an energy.all and a forces.all file." << endl;
     62                cout << "<prefix>\tprefix of energy and forces file." << endl;
     63                cout << "<outputdir>\tcreated plotfiles and datafiles are placed into this directory " << endl;
     64                cout << "[elementsdb]\tpath to elements database, needed for shieldings." << endl;
     65                return 1;
     66        } else {
     67                dir = (char *) Malloc(sizeof(char)*(strlen(argv[2])+2), "main: *dir");
     68                strcpy(dir, "/");
     69                strcat(dir, argv[2]);
     70        }
     71
     72        if (argc > 4) {
     73                cout << "Loading periodentafel." << endl;
     74                periode = new periodentafel;
     75                periode->LoadPeriodentafel(argv[4]);
     76        }
     77
     78        // Test the given directory
     79        if (!TestParams(argc, argv))
     80                return 1;
     81
     82        // +++++++++++++++++ PARSING +++++++++++++++++++++++++++++++
     83
     84        // ------------- Parse through all Fragment subdirs --------
     85        if (!Energy.ParseFragmentMatrix(argv[1], dir, EnergySuffix,0,0)) return 1;
     86        Hcorrected = Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX,0,0);
     87        if (!Force.ParseFragmentMatrix(argv[1], dir, ForcesSuffix,0,0)) return 1;
     88        if (!Time.ParseFragmentMatrix(argv[1], dir, TimeSuffix, 10,1)) return 1;
     89        if (periode != NULL) { // also look for PAS values
     90                if (!Shielding.ParseFragmentMatrix(argv[1], dir, ShieldingSuffix, 1, 0)) return 1;
     91                if (!ShieldingPAS.ParseFragmentMatrix(argv[1], dir, ShieldingPASSuffix, 1, 0)) return 1;
     92        }
     93
     94        // ---------- Parse the TE Factors into an array -----------------
     95        if (!Energy.ParseIndices()) return 1;
     96        if (Hcorrected) Hcorrection.ParseIndices();
     97
     98        // ---------- Parse the Force indices into an array ---------------
     99        if (!Force.ParseIndices(argv[1])) return 1;
     100        if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return 1;
     101        if (!ForceFragments.ParseIndices(argv[1])) return 1;
     102
     103        // ---------- Parse the shielding indices into an array ---------------
     104        if (periode != NULL) { // also look for PAS values
     105                if(!Shielding.ParseIndices(argv[1])) return 1;
     106                if(!ShieldingPAS.ParseIndices(argv[1])) return 1;
     107                if (!ShieldingFragments.AllocateMatrix(Shielding.Header, Shielding.MatrixCounter, Shielding.RowCounter, Shielding.ColumnCounter)) return 1;
     108                if (!ShieldingPASFragments.AllocateMatrix(ShieldingPAS.Header, ShieldingPAS.MatrixCounter, ShieldingPAS.RowCounter, ShieldingPAS.ColumnCounter)) return 1;
     109                if(!ShieldingFragments.ParseIndices(argv[1])) return 1;
     110                if(!ShieldingPASFragments.ParseIndices(argv[1])) return 1;
     111        }
     112
     113        // ---------- Parse the KeySets into an array ---------------
     114        if (!KeySet.ParseKeySets(argv[1], Force.RowCounter, Force.MatrixCounter)) return 1;
     115        if (!KeySet.ParseManyBodyTerms()) return 1;
     116
     117        // ---------- Parse fragment files created by 'joiner' into an array -------------
     118        if (!EnergyFragments.ParseFragmentMatrix(argv[1], dir, EnergyFragmentSuffix,0,0)) return 1;
     119        if (Hcorrected) HcorrectionFragments.ParseFragmentMatrix(argv[1], dir, HcorrectionFragmentSuffix,0,0);
     120        if (!ForceFragments.ParseFragmentMatrix(argv[1], dir, ForceFragmentSuffix,0,0)) return 1;
     121        if (periode != NULL) { // also look for PAS values
     122                if (!ShieldingFragments.ParseFragmentMatrix(argv[1], dir, ShieldingFragmentSuffix, 1, 0)) return 1;
     123                if (!ShieldingPASFragments.ParseFragmentMatrix(argv[1], dir, ShieldingPASFragmentSuffix, 1, 0)) return 1;
     124        }
     125
     126        // +++++++++++++++ TESTING ++++++++++++++++++++++++++++++
     127
     128        // print energy and forces to file
     129        filename.str("");
     130        filename << argv[3] << "/" << "energy-forces.all";
     131        output.open(filename.str().c_str(), ios::out);
     132        output << endl << "Total Energy" << endl << "==============" << endl << Energy.Header << endl;
     133        for(int j=0;j<Energy.RowCounter[Energy.MatrixCounter];j++) {
     134                for(int k=0;k<Energy.ColumnCounter;k++)
     135                        output << scientific << Energy.Matrix[ Energy.MatrixCounter ][j][k] << "\t";
     136                output << endl;
     137        }
     138        output << endl;
     139
     140        output << endl << "Total Forces" << endl << "===============" << endl << Force.Header << endl;
     141        for(int j=0;j<Force.RowCounter[Force.MatrixCounter];j++) {
     142                for(int k=0;k<Force.ColumnCounter;k++)
     143                        output << scientific << Force.Matrix[ Force.MatrixCounter ][j][k] << "\t";
     144                output << endl;
     145        }
     146        output << endl;
     147
     148        if (periode != NULL) { // also look for PAS values
     149                output << endl << "Total Shieldings" << endl << "===============" << endl << Shielding.Header << endl;
     150                for(int j=0;j<Shielding.RowCounter[Shielding.MatrixCounter];j++) {
     151                        for(int k=0;k<Shielding.ColumnCounter;k++)
     152                                output << scientific << Shielding.Matrix[ Shielding.MatrixCounter ][j][k] << "\t";
     153                        output << endl;
     154                }
     155                output << endl;
     156
     157                output << endl << "Total Shieldings PAS" << endl << "===============" << endl << ShieldingPAS.Header << endl;
     158                for(int j=0;j<ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter];j++) {
     159                        for(int k=0;k<ShieldingPAS.ColumnCounter;k++)
     160                                output << scientific << ShieldingPAS.Matrix[ ShieldingPAS.MatrixCounter ][j][k] << "\t";
     161                        output << endl;
     162                }
     163                output << endl;
     164        }
     165
     166        output << endl << "Total Times" << endl << "===============" << endl << Time.Header << endl;
     167        for(int j=0;j<Time.RowCounter[Time.MatrixCounter];j++) {
     168                for(int k=0;k<Time.ColumnCounter;k++) {
     169                        output << scientific << Time.Matrix[ Time.MatrixCounter ][j][k] << "\t";
     170                }
     171                output << endl;
     172        }
     173        output << endl;
     174        output.close();
     175        for(int k=0;k<Time.ColumnCounter;k++)
     176                Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k] = Time.Matrix[ Time.MatrixCounter ][Time.RowCounter[Time.MatrixCounter]-1][k];
     177
     178        // +++++++++++++++ ANALYZING ++++++++++++++++++++++++++++++
     179
     180        cout << "Analyzing ..." << endl;
     181
     182        // ======================================= Creating the data files ==============================================================
     183
     184        // +++++++++++++++++++++++++++++++++++++++ Plotting Simtime vs Bond Order
     185        // +++++++++++++++++++++++++++++++++++++++ Plotting Delta Simtime vs Bond Order
     186        if (!OpenOutputFile(output, argv[3], "SimTime-Order.dat" )) return false;
     187        if (!OpenOutputFile(output2, argv[3], "DeltaSimTime-Order.dat" )) return false;
     188        for(int j=Time.RowCounter[Time.MatrixCounter];j--;)
     189                for(int k=Time.ColumnCounter;k--;) {
     190                        Time.Matrix[ Time.MatrixCounter ][j][k] = 0.;
     191                }
     192        counter = 0;
     193        output << "#Order\tFrag.No.\t" << Time.Header << endl;
     194        output2 << "#Order\tFrag.No.\t" << Time.Header << endl;
     195        for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     196                for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;)
     197                        for(int j=Time.RowCounter[Time.MatrixCounter];j--;)
     198                                for(int k=Time.ColumnCounter;k--;) {
     199                                        Time.Matrix[ Time.MatrixCounter ][j][k] += Time.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
     200                                }
     201                counter += KeySet.FragmentsPerOrder[BondOrder];
     202                output << BondOrder+1 << "\t" << counter;
     203                output2 << BondOrder+1 << "\t" << counter;
     204                for(int k=0;k<Time.ColumnCounter;k++) {
     205                        output << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k];
     206                        if (fabs(Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k]) > MYEPSILON)
     207                                output2 << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k] / Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k];
     208                        else
     209                                output2 << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k];
     210                }
     211                output << endl;
     212                output2 << endl;
     213        }
     214        output.close();
     215        output2.close();
     216
     217        // +++++++++++++++++++++++++++++++++++++++ Plotting shieldings
     218
     219        if (periode != NULL) { // also look for PAS values
     220                if (!CreateDataDeltaForcesOrderPerAtom(ShieldingPAS, ShieldingPASFragments, KeySet, argv[3], "DeltaShieldingsPAS-Order", "Plot of error between approximated shieldings and full shieldings versus the Bond Order", datum)) return 1;
     221                if (!CreateDataForcesOrderPerAtom(ShieldingPASFragments, KeySet, argv[3], "ShieldingsPAS-Order", "Plot of approximated shieldings versus the Bond Order", datum)) return 1;
     222                if (!AppendOutputFile(output, argv[3], "ShieldingsPAS-Order.dat" )) return false;
     223                output << endl << "# Full" << endl;
     224                for(int j=0;j<ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter];j++) {
     225                        output << j << "\t";
     226                        for(int k=0;k<ShieldingPAS.ColumnCounter;k++)
     227                                output << scientific << ShieldingPAS.Matrix[ ShieldingPAS.MatrixCounter ][j][k] << "\t"; //*(((k>1) && (k<6))? 1.e6 : 1.) << "\t";
     228                        output << endl;
     229                }
     230        }
     231        output.close();
     232
     233
     234        // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in energy to full QM
     235        if (!CreateDataDeltaEnergyOrder(Energy, EnergyFragments, KeySet, argv[3], "DeltaEnergies-Order", "Plot of error between approximated and full energies energies versus the Bond Order", datum)) return 1;
     236
     237        // +++++++++++++++++++++++++++++++++++Plotting Energies vs. Order
     238        if (!CreateDataEnergyOrder(EnergyFragments, KeySet, argv[3], "Energies-Order", "Plot of approximated energies versus the Bond Order", datum)) return 1;
     239
     240        // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in forces to full QM
     241        if (!CreateDataDeltaForcesOrderPerAtom(Force, ForceFragments, KeySet, argv[3], "DeltaForces-Order", "Plot of error between approximated forces and full forces versus the Bond Order", datum)) return 1;
     242
     243        // min force
     244        if (!CreateDataDeltaForcesOrder(Force, ForceFragments, KeySet, argv[3], "DeltaMinForces-Order", "Plot of min error between approximated forces and full forces versus the Bond Order", datum, CreateMinimumForce)) return 1;
     245
     246        // mean force
     247        if (!CreateDataDeltaForcesOrder(Force, ForceFragments, KeySet, argv[3], "DeltaMeanForces-Order", "Plot of mean error between approximated forces and full forces versus the Bond Order", datum, CreateMeanForce)) return 1;
     248
     249        // max force
     250        if (!CreateDataDeltaForcesOrder(Force, ForceFragments, KeySet, argv[3], "DeltaMaxForces-Order", "Plot of max error between approximated forces and full forces versus the Bond Order", datum, CreateMaximumForce)) return 1;
     251
     252        // ++++++++++++++++++++++++++++++++++++++Plotting Forces vs. Order
     253        if (!CreateDataForcesOrderPerAtom(ForceFragments, KeySet, argv[3], "Forces-Order", "Plot of approximated forces versus the Bond Order", datum)) return 1;
     254        if (!AppendOutputFile(output, argv[3], "Forces-Order.dat" )) return false;
     255        output << endl << "# Full" << endl;
     256        for(int j=0;j<Force.RowCounter[Force.MatrixCounter];j++) {
     257                output << j << "\t";
     258                for(int k=0;k<Force.ColumnCounter;k++)
     259                        output << scientific << Force.Matrix[ Force.MatrixCounter ][j][k] << "\t";
     260                output << endl;
     261        }
     262        output.close();
     263        // min force
     264        if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MinForces-Order", "Plot of min approximated forces versus the Bond Order", datum, CreateMinimumForce)) return 1;
     265
     266        // mean force
     267        if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MeanForces-Order", "Plot of mean approximated forces versus the Bond Order", datum, CreateMeanForce)) return 1;
     268
     269        // max force
     270        if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MaxForces-Order", "Plot of max approximated forces versus the Bond Order", datum, CreateMaximumForce)) return 1;
     271
     272        // ++++++++++++++++++++++++++++++++++++++Plotting vector sum (should be 0) vs. bond order
     273        if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "VectorSum-Order", "Plot of vector sum of the approximated forces versus the Bond Order", datum, CreateVectorSumForce)) return 1;
     274
     275        // +++++++++++++++++++++++++++++++Plotting energyfragments vs. order
     276        if (!CreateDataFragment(EnergyFragments, KeySet, argv[3], "Energies-Fragment", "Plot of fragment energy versus the Fragment No", datum, CreateEnergy)) return 1;
     277        if (!CreateDataFragment(EnergyFragments, KeySet, argv[3], "Energies-FragmentOrder", "Plot of fragment energy of each Fragment No vs. Bond Order", datum, CreateEnergy)) return 1;
     278        if (!CreateDataFragmentOrder(EnergyFragments, KeySet, argv[3], "MaxEnergies-FragmentOrder", "Plot of maximum of fragment energy vs. Bond Order", datum, CreateMaxFragmentOrder)) return 1;
     279        if (!CreateDataFragmentOrder(EnergyFragments, KeySet, argv[3], "MinEnergies-FragmentOrder", "Plot of minimum of fragment energy vs. Bond Order", datum, CreateMinFragmentOrder)) return 1;
     280
     281        // +++++++++++++++++++++++++++++++Ploting min/mean/max forces for each fragment
     282        // min force
     283        if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MinForces-Fragment", "Plot of min approximated forces versus the Fragment No", datum, CreateMinimumForce)) return 1;
     284
     285        // mean force
     286        if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MeanForces-Fragment", "Plot of mean approximated forces versus the Fragment No", datum, CreateMeanForce)) return 1;
     287
     288        // max force
     289        if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MaxForces-Fragment", "Plot of max approximated forces versus the Fragment No", datum, CreateMaximumForce)) return 1;
     290
     291        // +++++++++++++++++++++++++++++++Ploting min/mean/max forces for each fragment per order
     292        // min force
     293        if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MinForces-FragmentOrder", "Plot of min approximated forces of each Fragment No vs. Bond Order", datum, CreateMinimumForce)) return 1;
     294
     295        // mean force
     296        if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MeanForces-FragmentOrder", "Plot of mean approximated forces of each Fragment No vs. Bond Order", datum, CreateMeanForce)) return 1;
     297
     298        // max force
     299        if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MaxForces-FragmentOrder", "Plot of max approximated forces of each Fragment No vs. Bond Order", datum, CreateMaximumForce)) return 1;
     300
     301        // ======================================= Creating the plot files ==============================================================
     302
     303        Orderxrange << "[1:" << KeySet.Order << "]";
     304        Fragmentxrange << "[0:" << KeySet.FragmentCounter+1 << "]";
     305        yrange.str("[1e-8:1e+1]");
     306
     307        // +++++++++++++++++++++++++++++++++++++++ Plotting Simtime vs Bond Order
     308        if (!CreatePlotOrder(Time, KeySet, argv[3], "SimTime-Order", 1, "below", "y", "",       1, 1, "bond order k", "Evaluation time [s]", Orderxrange.str().c_str(), "", "1" , "with linespoints", EnergyPlotLine)) return 1;
     309
     310        // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in energy to full QM
     311        if (!CreatePlotOrder(Energy, KeySet, argv[3], "DeltaEnergies-Order", 1, "outside", "y", "",     1, 1, "bond order k", "absolute error in energy [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsEnergyPlotLine)) return 1;
     312
     313        // +++++++++++++++++++++++++++++++++++Plotting Energies vs. Order
     314        if (!CreatePlotOrder(Energy, KeySet, argv[3], "Energies-Order", 1, "outside", "", "",   1, 1, "bond order k", "approximate energy [Ht]", Orderxrange.str().c_str(), "", "1" , "with linespoints", EnergyPlotLine)) return 1;
     315
     316        // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in forces to full QM
     317        yrange.str("[1e-8:1e+0]");
     318        // min force
     319        if (!CreatePlotOrder(Force, KeySet, argv[3], "DeltaMinForces-Order", 2, "top right", "y", "",   1, 1, "bond order k", "absolute error in min force [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;
     320
     321        // mean force
     322        if (!CreatePlotOrder(Force, KeySet, argv[3], "DeltaMeanForces-Order", 2, "top right", "y", "",  1, 1, "bond order k", "absolute error in mean force [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsFirstForceValuePlotLine)) return 1;
     323
     324        // max force
     325        if (!CreatePlotOrder(Force, KeySet, argv[3], "DeltaMaxForces-Order", 2, "top right", "y", "",   1, 1, "bond order k", "absolute error in max force [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;
     326
     327        // min/mean/max comparison for total force
     328        if(!OpenOutputFile(output, argv[3], "DeltaMinMeanMaxTotalForce-Order.pyx")) return 1;
     329        CreatePlotHeader(output, "DeltaMinMeanMaxTotalForce-Order", 1, "bottom left", "y", NULL,        1, 1, "bond order k", "absolute error in total forces [Ht/a.u.]");
     330        output << "plot " << Orderxrange.str().c_str() << " [1e-8:1e+0] \\" << endl;
     331        output << "'DeltaMinForces-Order.dat' title 'minimum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints, \\" << endl;
     332        output << "'DeltaMeanForces-Order.dat' title 'mean' using 1:(abs($" << 8 << ")) with linespoints, \\" << endl;
     333        output << "'DeltaMaxForces-Order.dat' title 'maximum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints" << endl;
     334        output.close();
     335
     336        // ++++++++++++++++++++++++++++++++++++++Plotting Forces vs. Order
     337        // min force
     338        if (!CreatePlotOrder(Force, KeySet, argv[3], "MinForces-Order", 2, "bottom right", "y", "",     1, 1, "bond order k", "absolute approximated min force [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;
     339
     340        // mean force
     341        if (!CreatePlotOrder(Force, KeySet, argv[3], "MeanForces-Order", 2, "bottom right", "y", "",    1, 1, "bond order k", "absolute approximated mean force [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", AbsFirstForceValuePlotLine)) return 1;
     342
     343        // max force
     344        if (!CreatePlotOrder(Force, KeySet, argv[3], "MaxForces-Order", 2, "bottom right", "y", "",     1, 1, "bond order k", "absolute approximated max force [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;
     345
     346        // min/mean/max comparison for total force
     347        if(!OpenOutputFile(output, argv[3],"MinMeanMaxTotalForce-Order.pyx")) return 1;
     348        CreatePlotHeader(output, "MinMeanMaxTotalForce-Order", 1, "bottom left", "y", NULL, 1, 1, "bond order k", "absolute total force [Ht/a.u.]");
     349        output << "plot "<< Orderxrange.str().c_str() << " [1e-8:1e+0] \\" << endl;
     350        output << "'MinForces-Order.dat' title 'minimum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints, \\" << endl;
     351        output << "'MeanForces-Order.dat' title 'mean' using 1:(abs($" << 8 << ")) with linespoints, \\" << endl;
     352        output << "'MaxForces-Order.dat' title 'maximum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints" << endl;
     353        output.close();
     354
     355        // ++++++++++++++++++++++++++++++++++++++Plotting vector sum vs. Order
     356
     357        if (!CreatePlotOrder(Force, KeySet, argv[3], "VectorSum-Order", 2, "bottom right", "y" ,"", 1, 1, "bond order k", "vector sum of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;
     358
     359        // +++++++++++++++++++++++++++++++Plotting energyfragments vs. order
     360        yrange.str("");
     361        yrange << "[" << EnergyFragments.FindMinValue() << ":" << EnergyFragments.FindMaxValue() << "]";
     362        if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "Energies-Fragment", 5, "below", "y", "", 1, 5, "fragment number", "Energies of each fragment [Ht]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with points", AbsEnergyPlotLine)) return 1;
     363        if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "Energies-FragmentOrder", 5, "below", "y", "", 1, 1, "bond order", "Energies of each fragment [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with points", AbsEnergyPlotLine)) return 1;
     364        if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "MaxEnergies-FragmentOrder", 5, "below", "y", "", 1, 1, "bond order", "Maximum fragment energy [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsEnergyPlotLine)) return 1;
     365        if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "MinEnergies-FragmentOrder", 5, "below", "y", "", 1, 1, "bond order", "Minimum fragment energy [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsEnergyPlotLine)) return 1;
     366
     367        // +++++++++++++++++++++++++++++++=Ploting min/mean/max forces for each fragment
     368        yrange.str("");
     369        yrange << "[" << ForceFragments.FindMinValue() << ":" << ForceFragments.FindMaxValue()<< "]";
     370        // min
     371        if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MinForces-Fragment", 5, "below", "y", "set boxwidth 0.2", 1, 5, "fragment number", "minimum of approximated forces [Ht/a.u.]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with boxes fillcolor", BoxesForcePlotLine)) return 1;
     372
     373        // mean
     374        if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MeanForces-Fragment", 5, "below", "y", "set boxwidth 0.2", 1, 5, "fragment number", "mean of approximated forces [Ht/a.u.]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with boxes fillcolor", BoxesFirstForceValuePlotLine)) return 1;
     375
     376        // max
     377        if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MaxForces-Fragment", 5, "below", "y", "set boxwidth 0.2", 1, 5, "fragment number", "maximum of approximated forces [Ht/a.u.]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with boxes fillcolor", BoxesForcePlotLine)) return 1;
     378
     379        // +++++++++++++++++++++++++++++++=Ploting min/mean/max forces for each fragment per bond order
     380        // min
     381        if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MinForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "minimum of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesForcePlotLine)) return 1;
     382
     383        // mean
     384        if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MeanForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "mean of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesFirstForceValuePlotLine)) return 1;
     385
     386        // max
     387        if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MaxForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "maximum of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesForcePlotLine)) return 1;
     388
     389        // +++++++++++++++++++++++++++++++=Ploting approximated and true shielding for each atom
     390        if (periode != NULL) { // also look for PAS values
     391                if(!OpenOutputFile(output, argv[3], "ShieldingsPAS-Order.pyx")) return 1;
     392                if(!OpenOutputFile(output2, argv[3], "DeltaShieldingsPAS-Order.pyx")) return 1;
     393                CreatePlotHeader(output, "ShieldingsPAS-Order", 1, "top right", NULL, NULL,     1, 5, "nuclei index", "iso chemical shielding value [ppm]");
     394                CreatePlotHeader(output2, "DeltaShieldingsPAS-Order", 1, "top right", NULL, NULL,       1, 5, "nuclei index", "iso chemical shielding value [ppm]");
     395                double step=0.8/KeySet.Order;
     396                output << "set boxwidth " << step << endl;
     397                output << "plot [0:" << ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter]+10 << "]\\" << endl;
     398                output2 << "plot [0:" << ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter]+10 << "]\\" << endl;
     399                for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     400                        output << "'ShieldingsPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1+" << step*(double)BondOrder << "):7 with boxes, \\" << endl;
     401                        output2 << "'DeltaShieldingsPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1):7 with linespoints";
     402                        if (BondOrder-1 != KeySet.Order)
     403                                output2 << ", \\" << endl;
     404                }
     405                output << "'ShieldingsPAS-Order.dat' index " << KeySet.Order << " title 'Full' using ($1+" << step*(double)KeySet.Order << "):7 with boxes" << endl;
     406                output.close();
     407                output2.close();
     408        }
     409
     410        // create Makefile
     411        if(!OpenOutputFile(output, argv[3], "Makefile")) return 1;
     412        output << "PYX = $(shell ls *.pyx)" << endl << endl;
     413        output << "EPS = $(PYX:.pyx=.eps)" << endl << endl;
     414        output << "%.eps: %.pyx" << endl;
     415        output << "\t~/build/pyxplot/pyxplot $<" << endl << endl;
     416        output << "all: $(EPS)" << endl << endl;
     417        output << ".PHONY: clean" << endl;
     418        output << "clean:" << endl;
     419        output << "\trm -rf $(EPS)" << endl;
     420        output.close();
     421
     422        // ++++++++++++++++ exit ++++++++++++++++++++++++++++++++++
     423        delete(periode);
     424        Free((void **)&dir, "main: *dir");
     425        cout << "done." << endl;
     426        return 0;
    427427};
    428428
  • src/atom.cpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    1414{
    1515        Name = NULL;
    16   previous = NULL;
    17   next = NULL;
    18   father = this;  // generally, father is itself
    19   Ancestor = NULL;
    20   type = NULL;
    21   sort = NULL;
    22   FixedIon = 0;
    23   nr = -1;
    24   GraphNr = -1;
    25   ComponentNr = NULL;
    26   IsCyclic = false;
    27   SeparationVertex = false;
    28   LowpointNr = -1;
    29   AdaptiveOrder = 0;
    30   MaxOrder = false;
     16        previous = NULL;
     17        next = NULL;
     18        father = this;  // generally, father is itself
     19        Ancestor = NULL;
     20        type = NULL;
     21        sort = NULL;
     22        FixedIon = 0;
     23        nr = -1;
     24        GraphNr = -1;
     25        ComponentNr = NULL;
     26        IsCyclic = false;
     27        SeparationVertex = false;
     28        LowpointNr = -1;
     29        AdaptiveOrder = 0;
     30        MaxOrder = false;
    3131};
    3232
     
    3636{
    3737        Free((void **)&Name, "atom::~atom: *Name");
    38   Free((void **)&ComponentNr, "atom::~atom: *ComponentNr");
     38        Free((void **)&ComponentNr, "atom::~atom: *ComponentNr");
    3939};
    4040
     
    4545atom *atom::GetTrueFather()
    4646{
    47   atom *walker = this;
    48   do {
    49     if (walker == walker->father) // top most father is the one that points on itself
    50       break;
    51     walker = walker->father;
    52   } while (walker != NULL);
    53   return walker;
     47        atom *walker = this;
     48        do {
     49                if (walker == walker->father) // top most father is the one that points on itself
     50                        break;
     51                walker = walker->father;
     52        } while (walker != NULL);
     53        return walker;
    5454};
    5555
     
    6161bool atom::Output(int ElementNo, int AtomNo, ofstream *out) const
    6262{
    63   if (out != NULL) {
    64     *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t"  << fixed << setprecision(9) << showpoint;
    65     *out << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2];
    66     *out << "\t" << FixedIon;
    67     if (v.Norm() > MYEPSILON)
    68       *out << "\t" << scientific << setprecision(6) << v.x[0] << "\t" << v.x[1] << "\t" << v.x[2] << "\t";
    69     *out << " # Number in molecule " << nr << endl;
    70     return true;
    71   } else
    72     return false;
     63        if (out != NULL) {
     64                *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t"        << fixed << setprecision(9) << showpoint;
     65                *out << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2];
     66                *out << "\t" << FixedIon;
     67                if (v.Norm() > MYEPSILON)
     68                        *out << "\t" << scientific << setprecision(6) << v.x[0] << "\t" << v.x[1] << "\t" << v.x[2] << "\t";
     69                *out << " # Number in molecule " << nr << endl;
     70                return true;
     71        } else
     72                return false;
    7373};
    7474
     
    7878bool atom::OutputXYZLine(ofstream *out) const
    7979{
    80   if (out != NULL) {
    81     *out << type->symbol << "\t" << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2] << "\t" << endl;
    82     return true;
    83   } else
    84     return false;
     80        if (out != NULL) {
     81                *out << type->symbol << "\t" << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2] << "\t" << endl;
     82                return true;
     83        } else
     84                return false;
    8585};
    8686
    8787ostream & operator << (ostream &ost, atom &a)
    8888{
    89   ost << "[" << a.Name << "|" << &a << "]";
    90   return ost;
     89        ost << "[" << a.Name << "|" << &a << "]";
     90        return ost;
    9191};
    9292
     
    9797bool atom::Compare(atom &ptr)
    9898{
    99   if (nr < ptr.nr)
    100     return true;
    101   else
    102     return false;
     99        if (nr < ptr.nr)
     100                return true;
     101        else
     102                return false;
    103103};
    104104
    105105bool operator < (atom &a, atom &b)
    106106{
    107   return a.Compare(b);
     107        return a.Compare(b);
    108108};
    109109
  • src/bond.cpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    1616        leftatom = NULL;
    1717        rightatom = NULL;
    18   previous = NULL;
    19   next = NULL;
     18        previous = NULL;
     19        next = NULL;
    2020        nr = -1;
    2121        HydrogenBond = 0;
    2222        BondDegree = 0;
    23   Used = white;
    24   Cyclic = false;
    25   Type = Undetermined;
     23        Used = white;
     24        Cyclic = false;
     25        Type = Undetermined;
    2626};
    2727
     
    3636        leftatom = left;
    3737        rightatom = right;
    38   previous = NULL;
    39   next = NULL;
     38        previous = NULL;
     39        next = NULL;
    4040        HydrogenBond = 0;
    41   if ((left != NULL) && (right != NULL)) {
    42         if ((left->type != NULL) && (left->type->Z == 1))
    43                 HydrogenBond++;
    44         if ((right->type != NULL) && (right->type->Z == 1))
    45                 HydrogenBond++;
    46   }
    47   BondDegree = degree;
    48   nr = number;
    49   Used = white;
    50   Cyclic = false;
     41        if ((left != NULL) && (right != NULL)) {
     42                if ((left->type != NULL) && (left->type->Z == 1))
     43                        HydrogenBond++;
     44                if ((right->type != NULL) && (right->type->Z == 1))
     45                        HydrogenBond++;
     46        }
     47        BondDegree = degree;
     48        nr = number;
     49        Used = white;
     50        Cyclic = false;
    5151};
    5252bond::bond(atom *left, atom *right)
    5353{
    54   leftatom = left;
    55   rightatom = right;
    56   previous = NULL;
    57   next = NULL;
    58   HydrogenBond = 0;
    59   if ((left != NULL) && (right != NULL)) {
    60     if ((left->type != NULL) && (left->type->Z == 1))
    61       HydrogenBond++;
    62     if ((right->type != NULL) && (right->type->Z == 1))
    63       HydrogenBond++;
    64   }
    65   BondDegree = 1;
    66   nr = 0;
    67   Used = white;
    68   Cyclic = false;
     54        leftatom = left;
     55        rightatom = right;
     56        previous = NULL;
     57        next = NULL;
     58        HydrogenBond = 0;
     59        if ((left != NULL) && (right != NULL)) {
     60                if ((left->type != NULL) && (left->type->Z == 1))
     61                        HydrogenBond++;
     62                if ((right->type != NULL) && (right->type->Z == 1))
     63                        HydrogenBond++;
     64        }
     65        BondDegree = 1;
     66        nr = 0;
     67        Used = white;
     68        Cyclic = false;
    6969};
    7070
     
    7373bond::~bond()
    7474{
    75   // remove this node from the list structure
    76   if (previous != NULL) {
    77     previous->next = next;
    78   }
    79   if (next != NULL) {
    80     next->previous = previous;
    81   }
     75        // remove this node from the list structure
     76        if (previous != NULL) {
     77                previous->next = next;
     78        }
     79        if (next != NULL) {
     80                next->previous = previous;
     81        }
    8282};
    8383
    8484ostream & operator << (ostream &ost, bond &b)
    8585{
    86   ost << "[" << b.leftatom->Name << " <" << b.BondDegree << "(H" << b.HydrogenBond << ")>" << b.rightatom->Name << "]";
    87   return ost;
     86        ost << "[" << b.leftatom->Name << " <" << b.BondDegree << "(H" << b.HydrogenBond << ")>" << b.rightatom->Name << "]";
     87        return ost;
    8888};
    8989
     
    9494atom * bond::GetOtherAtom(atom *Atom) const
    9595{
    96   if(leftatom == Atom)
    97     return rightatom;
    98   if(rightatom == Atom)
    99     return leftatom;
    100   return NULL;
     96        if(leftatom == Atom)
     97                return rightatom;
     98        if(rightatom == Atom)
     99                return leftatom;
     100        return NULL;
    101101};
    102102
     
    107107bond * bond::GetFirstBond()
    108108{
    109   return GetFirst(this);
     109        return GetFirst(this);
    110110};
    111111
     
    116116bond * bond::GetLastBond()
    117117{
    118   return GetLast(this);
     118        return GetLast(this);
    119119};
    120120
     
    124124enum Shading bond::IsUsed()
    125125{
    126   return Used;
     126        return Used;
    127127};
    128128
     
    133133bool bond::Contains(const atom *ptr)
    134134{
    135   return ((leftatom == ptr) || (rightatom == ptr));
     135        return ((leftatom == ptr) || (rightatom == ptr));
    136136};
    137137
     
    142142bool bond::Contains(const int number)
    143143{
    144   return ((leftatom->nr == number) || (rightatom->nr == number));
     144        return ((leftatom->nr == number) || (rightatom->nr == number));
    145145};
    146146
     
    149149 */
    150150bool bond::MarkUsed(enum Shading color) {
    151   if (Used == black) {
    152     cerr << "ERROR: Bond " << this << " was already marked black!." << endl;
    153     return false;
    154   } else {
    155     Used = color;
    156     return true;
    157   }
     151        if (Used == black) {
     152                cerr << "ERROR: Bond " << this << " was already marked black!." << endl;
     153                return false;
     154        } else {
     155                Used = color;
     156                return true;
     157        }
    158158};
    159159
     
    162162 */
    163163void bond::ResetUsed() {
    164   Used = white;
     164        Used = white;
    165165};
  • src/boundary.cpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    1 #include "molecules.hpp"
    21#include "boundary.hpp"
    32
    43#define DEBUG 1
    5 #define DoTecplotOutput 0
     4#define DoSingleStepOutput 0
     5#define DoTecplotOutput 1
    66#define DoRaster3DOutput 1
     7#define DoVRMLOutput 1
    78#define TecplotSuffix ".dat"
    89#define Raster3DSuffix ".r3d"
     10#define VRMLSUffix ".wrl"
     11#define HULLEPSILON MYEPSILON
    912
    1013// ======================================== Points on Boundary =================================
     
    1215BoundaryPointSet::BoundaryPointSet()
    1316{
    14   LinesCount = 0;
    15   Nr = -1;
     17        LinesCount = 0;
     18        Nr = -1;
    1619}
    1720;
     
    1922BoundaryPointSet::BoundaryPointSet(atom *Walker)
    2023{
    21   node = Walker;
    22   LinesCount = 0;
    23   Nr = Walker->nr;
     24        node = Walker;
     25        LinesCount = 0;
     26        Nr = Walker->nr;
    2427}
    2528;
     
    2730BoundaryPointSet::~BoundaryPointSet()
    2831{
    29   cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl;
    30   node = NULL;
    31 }
    32 ;
    33 
    34 void
    35 BoundaryPointSet::AddLine(class BoundaryLineSet *line)
    36 {
    37   cout << Verbose(6) << "Adding " << *this << " to line " << *line << "."
    38       << endl;
    39   if (line->endpoints[0] == this)
    40     {
    41       lines.insert(LinePair(line->endpoints[1]->Nr, line));
    42     }
    43   else
    44     {
    45       lines.insert(LinePair(line->endpoints[0]->Nr, line));
    46     }
    47   LinesCount++;
     32        cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl;
     33        if (!lines.empty())
     34                cerr << "WARNING: Memory Leak! I " << *this << " am still connected to some lines." << endl;
     35        node = NULL;
     36}
     37;
     38
     39void BoundaryPointSet::AddLine(class BoundaryLineSet *line)
     40{
     41        cout << Verbose(6) << "Adding " << *this << " to line " << *line << "."
     42                        << endl;
     43        if (line->endpoints[0] == this)
     44                {
     45                        lines.insert(LinePair(line->endpoints[1]->Nr, line));
     46                }
     47        else
     48                {
     49                        lines.insert(LinePair(line->endpoints[0]->Nr, line));
     50                }
     51        LinesCount++;
    4852}
    4953;
     
    5256operator <<(ostream &ost, BoundaryPointSet &a)
    5357{
    54   ost << "[" << a.Nr << "|" << a.node->Name << "]";
    55   return ost;
     58        ost << "[" << a.Nr << "|" << a.node->Name << "]";
     59        return ost;
    5660}
    5761;
     
    6165BoundaryLineSet::BoundaryLineSet()
    6266{
    63   for (int i = 0; i < 2; i++)
    64     endpoints[i] = NULL;
    65   TrianglesCount = 0;
    66   Nr = -1;
     67        for (int i = 0; i < 2; i++)
     68                endpoints[i] = NULL;
     69        TrianglesCount = 0;
     70        Nr = -1;
    6771}
    6872;
     
    7074BoundaryLineSet::BoundaryLineSet(class BoundaryPointSet *Point[2], int number)
    7175{
    72   // set number
    73   Nr = number;
    74   // set endpoints in ascending order
    75   SetEndpointsOrdered(endpoints, Point[0], Point[1]);
    76   // add this line to the hash maps of both endpoints
    77   Point[0]->AddLine(this); //Taken out, to check whether we can avoid unwanted double adding.
    78   Point[1]->AddLine(this); //
    79   // clear triangles list
    80   TrianglesCount = 0;
    81   cout << Verbose(5) << "New Line with endpoints " << *this << "." << endl;
     76        // set number
     77        Nr = number;
     78        // set endpoints in ascending order
     79        SetEndpointsOrdered(endpoints, Point[0], Point[1]);
     80        // add this line to the hash maps of both endpoints
     81        Point[0]->AddLine(this); //Taken out, to check whether we can avoid unwanted double adding.
     82        Point[1]->AddLine(this); //
     83        // clear triangles list
     84        TrianglesCount = 0;
     85        cout << Verbose(5) << "New Line with endpoints " << *this << "." << endl;
    8286}
    8387;
     
    8589BoundaryLineSet::~BoundaryLineSet()
    8690{
    87   for (int i = 0; i < 2; i++)
    88     {
    89       cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point "
    90           << *endpoints[i] << "." << endl;
    91       endpoints[i]->lines.erase(Nr);
    92       LineMap::iterator tester = endpoints[i]->lines.begin();
    93       tester++;
    94       if (tester == endpoints[i]->lines.end())
    95         {
    96           cout << Verbose(5) << *endpoints[i]
    97               << " has no more lines it's attached to, erasing." << endl;
    98           //delete(endpoints[i]);
    99         }
    100       else
    101         cout << Verbose(5) << *endpoints[i]
    102             << " has still lines it's attached to." << endl;
    103     }
     91        int Numbers[2];
     92        Numbers[0] = endpoints[1]->Nr;
     93        Numbers[1] = endpoints[0]->Nr;
     94        for (int i = 0; i < 2; i++) {
     95                cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl;
     96                endpoints[i]->lines.erase(Numbers[i]);
     97                if (endpoints[i]->lines.empty()) {
     98                        cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl;
     99                        if (endpoints[i] != NULL) {
     100                                delete(endpoints[i]);
     101                                endpoints[i] = NULL;
     102                        } else
     103                                cerr << "ERROR: Endpoint " << i << " has already been free'd." << endl;
     104                } else
     105                        cout << Verbose(5) << *endpoints[i] << " has still lines it's attached to." << endl;
     106        }
     107        if (!triangles.empty())
     108                cerr << "WARNING: Memory Leak! I " << *this << " am still connected to some triangles." << endl;
    104109}
    105110;
     
    108113BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle)
    109114{
    110   cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "."
    111       << endl;
    112   triangles.insert(TrianglePair(TrianglesCount, triangle));
    113   TrianglesCount++;
     115        cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "."
     116                        << endl;
     117        triangles.insert(TrianglePair(triangle->Nr, triangle));
     118        TrianglesCount++;
    114119}
    115120;
     
    118123operator <<(ostream &ost, BoundaryLineSet &a)
    119124{
    120   ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","
    121       << a.endpoints[1]->node->Name << "]";
    122   return ost;
     125        ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","
     126                        << a.endpoints[1]->node->Name << "]";
     127        return ost;
    123128}
    124129;
     
    129134BoundaryTriangleSet::BoundaryTriangleSet()
    130135{
    131   for (int i = 0; i < 3; i++)
    132     {
    133       endpoints[i] = NULL;
    134       lines[i] = NULL;
    135     }
    136   Nr = -1;
     136        for (int i = 0; i < 3; i++)
     137                {
     138                        endpoints[i] = NULL;
     139                        lines[i] = NULL;
     140                }
     141        Nr = -1;
    137142}
    138143;
    139144
    140145BoundaryTriangleSet::BoundaryTriangleSet(class BoundaryLineSet *line[3],
    141     int number)
    142 {
    143   // set number
    144   Nr = number;
    145   // set lines
    146   cout << Verbose(5) << "New triangle " << Nr << ":" << endl;
    147   for (int i = 0; i < 3; i++)
    148     {
    149       lines[i] = line[i];
    150       lines[i]->AddTriangle(this);
    151     }
    152   // get ascending order of endpoints
    153   map<int, class BoundaryPointSet *> OrderMap;
    154   for (int i = 0; i < 3; i++)
    155     // for all three lines
    156     for (int j = 0; j < 2; j++)
    157       { // for both endpoints
    158         OrderMap.insert(pair<int, class BoundaryPointSet *> (
    159             line[i]->endpoints[j]->Nr, line[i]->endpoints[j]));
    160         // and we don't care whether insertion fails
    161       }
    162   // set endpoints
    163   int Counter = 0;
    164   cout << Verbose(6) << " with end points ";
    165   for (map<int, class BoundaryPointSet *>::iterator runner = OrderMap.begin(); runner
    166       != OrderMap.end(); runner++)
    167     {
    168       endpoints[Counter] = runner->second;
    169       cout << " " << *endpoints[Counter];
    170       Counter++;
    171     }
    172   if (Counter < 3)
    173     {
    174       cerr << "ERROR! We have a triangle with only two distinct endpoints!"
    175           << endl;
    176       //exit(1);
    177     }
    178   cout << "." << endl;
     146                int number)
     147{
     148        // set number
     149        Nr = number;
     150        // set lines
     151        cout << Verbose(5) << "New triangle " << Nr << ":" << endl;
     152        for (int i = 0; i < 3; i++)
     153                {
     154                        lines[i] = line[i];
     155                        lines[i]->AddTriangle(this);
     156                }
     157        // get ascending order of endpoints
     158        map<int, class BoundaryPointSet *> OrderMap;
     159        for (int i = 0; i < 3; i++)
     160                // for all three lines
     161                for (int j = 0; j < 2; j++)
     162                        { // for both endpoints
     163                                OrderMap.insert(pair<int, class BoundaryPointSet *> (
     164                                                line[i]->endpoints[j]->Nr, line[i]->endpoints[j]));
     165                                // and we don't care whether insertion fails
     166                        }
     167        // set endpoints
     168        int Counter = 0;
     169        cout << Verbose(6) << " with end points ";
     170        for (map<int, class BoundaryPointSet *>::iterator runner = OrderMap.begin(); runner
     171                        != OrderMap.end(); runner++)
     172                {
     173                        endpoints[Counter] = runner->second;
     174                        cout << " " << *endpoints[Counter];
     175                        Counter++;
     176                }
     177        if (Counter < 3)
     178                {
     179                        cerr << "ERROR! We have a triangle with only two distinct endpoints!"
     180                                        << endl;
     181                        //exit(1);
     182                }
     183        cout << "." << endl;
    179184}
    180185;
     
    182187BoundaryTriangleSet::~BoundaryTriangleSet()
    183188{
    184   for (int i = 0; i < 3; i++)
    185     {
    186       cout << Verbose(5) << "Erasing triangle Nr." << Nr << endl;
    187       lines[i]->triangles.erase(Nr);
    188       TriangleMap::iterator tester = lines[i]->triangles.begin();
    189       tester++;
    190       if (tester == lines[i]->triangles.end())
    191         {
    192           cout << Verbose(5) << *lines[i]
    193               << " is no more attached to any triangle, erasing." << endl;
    194           delete (lines[i]);
    195         }
    196       else
    197         cout << Verbose(5) << *lines[i] << " is still attached to a triangle."
    198             << endl;
    199     }
     189        for (int i = 0; i < 3; i++) {
     190                cout << Verbose(5) << "Erasing triangle Nr." << Nr << endl;
     191                lines[i]->triangles.erase(Nr);
     192                if (lines[i]->triangles.empty()) {
     193                        cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl;
     194                        if (lines[i] != NULL) {
     195                                delete (lines[i]);
     196                                lines[i] = NULL;
     197                        } else
     198                                cerr << "ERROR: This line " << i << " has already been free'd." << endl;
     199                } else
     200                        cout << Verbose(5) << *lines[i] << " is still attached to a triangle." << endl;
     201        }
    200202}
    201203;
     
    204206BoundaryTriangleSet::GetNormalVector(Vector &OtherVector)
    205207{
    206   // get normal vector
    207   NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x,
    208       &endpoints[2]->node->x);
    209 
    210   // make it always point inward (any offset vector onto plane projected onto normal vector suffices)
    211   if (endpoints[0]->node->x.Projection(&OtherVector) > 0)
    212     NormalVector.Scale(-1.);
     208        // get normal vector
     209        NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x,
     210                        &endpoints[2]->node->x);
     211
     212        // make it always point inward (any offset vector onto plane projected onto normal vector suffices)
     213        if (NormalVector.Projection(&OtherVector) > 0)
     214                NormalVector.Scale(-1.);
    213215}
    214216;
     
    217219operator <<(ostream &ost, BoundaryTriangleSet &a)
    218220{
    219   ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","
    220       << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]";
    221   return ost;
     221        ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","
     222                        << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]";
     223        return ost;
    222224}
    223225;
     
    233235GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2)
    234236{
    235   class BoundaryLineSet * lines[2] =
    236     { line1, line2 };
    237   class BoundaryPointSet *node = NULL;
    238   map<int, class BoundaryPointSet *> OrderMap;
    239   pair<map<int, class BoundaryPointSet *>::iterator, bool> OrderTest;
    240   for (int i = 0; i < 2; i++)
    241     // for both lines
    242     for (int j = 0; j < 2; j++)
    243       { // for both endpoints
    244         OrderTest = OrderMap.insert(pair<int, class BoundaryPointSet *> (
    245             lines[i]->endpoints[j]->Nr, lines[i]->endpoints[j]));
    246         if (!OrderTest.second)
    247           { // if insertion fails, we have common endpoint
    248             node = OrderTest.first->second;
    249             cout << Verbose(5) << "Common endpoint of lines " << *line1
    250                 << " and " << *line2 << " is: " << *node << "." << endl;
    251             j = 2;
    252             i = 2;
    253             break;
    254           }
    255       }
    256   return node;
     237        class BoundaryLineSet * lines[2] =
     238                { line1, line2 };
     239        class BoundaryPointSet *node = NULL;
     240        map<int, class BoundaryPointSet *> OrderMap;
     241        pair<map<int, class BoundaryPointSet *>::iterator, bool> OrderTest;
     242        for (int i = 0; i < 2; i++)
     243                // for both lines
     244                for (int j = 0; j < 2; j++)
     245                        { // for both endpoints
     246                                OrderTest = OrderMap.insert(pair<int, class BoundaryPointSet *> (
     247                                                lines[i]->endpoints[j]->Nr, lines[i]->endpoints[j]));
     248                                if (!OrderTest.second)
     249                                        { // if insertion fails, we have common endpoint
     250                                                node = OrderTest.first->second;
     251                                                cout << Verbose(5) << "Common endpoint of lines " << *line1
     252                                                                << " and " << *line2 << " is: " << *node << "." << endl;
     253                                                j = 2;
     254                                                i = 2;
     255                                                break;
     256                                        }
     257                        }
     258        return node;
    257259}
    258260;
     
    268270GetBoundaryPoints(ofstream *out, molecule *mol)
    269271{
    270   atom *Walker = NULL;
    271   PointMap PointsOnBoundary;
    272   LineMap LinesOnBoundary;
    273   TriangleMap TrianglesOnBoundary;
    274 
    275   *out << Verbose(1) << "Finding all boundary points." << endl;
    276   Boundaries *BoundaryPoints = new Boundaries[NDIM]; // first is alpha, second is (r, nr)
    277   BoundariesTestPair BoundaryTestPair;
    278   Vector AxisVector, AngleReferenceVector, AngleReferenceNormalVector;
    279   double radius, angle;
    280   // 3a. Go through every axis
    281   for (int axis = 0; axis < NDIM; axis++)
    282     {
    283       AxisVector.Zero();
    284       AngleReferenceVector.Zero();
    285       AngleReferenceNormalVector.Zero();
    286       AxisVector.x[axis] = 1.;
    287       AngleReferenceVector.x[(axis + 1) % NDIM] = 1.;
    288       AngleReferenceNormalVector.x[(axis + 2) % NDIM] = 1.;
    289       //    *out << Verbose(1) << "Axisvector is ";
    290       //    AxisVector.Output(out);
    291       //    *out << " and AngleReferenceVector is ";
    292       //    AngleReferenceVector.Output(out);
    293       //    *out << "." << endl;
    294       //    *out << " and AngleReferenceNormalVector is ";
    295       //    AngleReferenceNormalVector.Output(out);
    296       //    *out << "." << endl;
    297       // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours
    298       Walker = mol->start;
    299       while (Walker->next != mol->end)
    300         {
    301           Walker = Walker->next;
    302           Vector ProjectedVector;
    303           ProjectedVector.CopyVector(&Walker->x);
    304           ProjectedVector.ProjectOntoPlane(&AxisVector);
    305           // correct for negative side
    306           //if (Projection(y) < 0)
    307           //angle = 2.*M_PI - angle;
    308           radius = ProjectedVector.Norm();
    309           if (fabs(radius) > MYEPSILON)
    310             angle = ProjectedVector.Angle(&AngleReferenceVector);
    311           else
    312             angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues
    313 
    314           //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl;
    315           if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0)
    316             {
    317               angle = 2. * M_PI - angle;
    318             }
    319           //*out << Verbose(2) << "Inserting " << *Walker << ": (r, alpha) = (" << radius << "," << angle << "): ";
    320           //ProjectedVector.Output(out);
    321           //*out << endl;
    322           BoundaryTestPair = BoundaryPoints[axis].insert(BoundariesPair(angle,
    323               DistancePair (radius, Walker)));
    324           if (BoundaryTestPair.second)
    325             { // successfully inserted
    326             }
    327           else
    328             { // same point exists, check first r, then distance of original vectors to center of gravity
    329               *out << Verbose(2)
    330                   << "Encountered two vectors whose projection onto axis "
    331                   << axis << " is equal: " << endl;
    332               *out << Verbose(2) << "Present vector: ";
    333               BoundaryTestPair.first->second.second->x.Output(out);
    334               *out << endl;
    335               *out << Verbose(2) << "New vector: ";
    336               Walker->x.Output(out);
    337               *out << endl;
    338               double tmp = ProjectedVector.Norm();
    339               if (tmp > BoundaryTestPair.first->second.first)
    340                 {
    341                   BoundaryTestPair.first->second.first = tmp;
    342                   BoundaryTestPair.first->second.second = Walker;
    343                   *out << Verbose(2) << "Keeping new vector." << endl;
    344                 }
    345               else if (tmp == BoundaryTestPair.first->second.first)
    346                 {
    347                   if (BoundaryTestPair.first->second.second->x.ScalarProduct(
    348                       &BoundaryTestPair.first->second.second->x)
    349                       < Walker->x.ScalarProduct(&Walker->x))
    350                     { // Norm() does a sqrt, which makes it a lot slower
    351                       BoundaryTestPair.first->second.second = Walker;
    352                       *out << Verbose(2) << "Keeping new vector." << endl;
    353                     }
    354                   else
    355                     {
    356                       *out << Verbose(2) << "Keeping present vector." << endl;
    357                     }
    358                 }
    359               else
    360                 {
    361                   *out << Verbose(2) << "Keeping present vector." << endl;
    362                 }
    363             }
    364         }
    365       // printing all inserted for debugging
    366       //    {
    367       //      *out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl;
    368       //      int i=0;
    369       //      for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
    370       //        if (runner != BoundaryPoints[axis].begin())
    371       //          *out << ", " << i << ": " << *runner->second.second;
    372       //        else
    373       //          *out << i << ": " << *runner->second.second;
    374       //        i++;
    375       //      }
    376       //      *out << endl;
    377       //    }
    378       // 3c. throw out points whose distance is less than the mean of left and right neighbours
    379       bool flag = false;
    380       do
    381         { // do as long as we still throw one out per round
    382           *out << Verbose(1)
    383               << "Looking for candidates to kick out by convex condition ... "
    384               << endl;
    385           flag = false;
    386           Boundaries::iterator left = BoundaryPoints[axis].end();
    387           Boundaries::iterator right = BoundaryPoints[axis].end();
    388           for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner
    389               != BoundaryPoints[axis].end(); runner++)
    390             {
    391               // set neighbours correctly
    392               if (runner == BoundaryPoints[axis].begin())
    393                 {
    394                   left = BoundaryPoints[axis].end();
    395                 }
    396               else
    397                 {
    398                   left = runner;
    399                 }
    400               left--;
    401               right = runner;
    402               right++;
    403               if (right == BoundaryPoints[axis].end())
    404                 {
    405                   right = BoundaryPoints[axis].begin();
    406                 }
    407               // check distance
    408 
    409               // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector)
    410                 {
    411                   Vector SideA, SideB, SideC, SideH;
    412                   SideA.CopyVector(&left->second.second->x);
    413                   SideA.ProjectOntoPlane(&AxisVector);
    414                   //          *out << "SideA: ";
    415                   //          SideA.Output(out);
    416                   //          *out << endl;
    417 
    418                   SideB.CopyVector(&right->second.second->x);
    419                   SideB.ProjectOntoPlane(&AxisVector);
    420                   //          *out << "SideB: ";
    421                   //          SideB.Output(out);
    422                   //          *out << endl;
    423 
    424                   SideC.CopyVector(&left->second.second->x);
    425                   SideC.SubtractVector(&right->second.second->x);
    426                   SideC.ProjectOntoPlane(&AxisVector);
    427                   //          *out << "SideC: ";
    428                   //          SideC.Output(out);
    429                   //          *out << endl;
    430 
    431                   SideH.CopyVector(&runner->second.second->x);
    432                   SideH.ProjectOntoPlane(&AxisVector);
    433                   //          *out << "SideH: ";
    434                   //          SideH.Output(out);
    435                   //          *out << endl;
    436 
    437                   // calculate each length
    438                   double a = SideA.Norm();
    439                   //double b = SideB.Norm();
    440                   //double c = SideC.Norm();
    441                   double h = SideH.Norm();
    442                   // calculate the angles
    443                   double alpha = SideA.Angle(&SideH);
    444                   double beta = SideA.Angle(&SideC);
    445                   double gamma = SideB.Angle(&SideH);
    446                   double delta = SideC.Angle(&SideH);
    447                   double MinDistance = a * sin(beta) / (sin(delta)) * (((alpha
    448                       < M_PI / 2.) || (gamma < M_PI / 2.)) ? 1. : -1.);
    449                   //          *out << Verbose(2) << " I calculated: a = " << a << ", h = " << h << ", beta(" << left->second.second->Name << "," << left->second.second->Name << "-" << right->second.second->Name << ") = " << beta << ", delta(" << left->second.second->Name << "," << runner->second.second->Name << ") = " << delta << ", Min = " << MinDistance << "." << endl;
    450                   //*out << Verbose(1) << "Checking CoG distance of runner " << *runner->second.second << " " << h << " against triangle's side length spanned by (" << *left->second.second << "," << *right->second.second << ") of " << MinDistance << "." << endl;
    451                   if ((fabs(h / fabs(h) - MinDistance / fabs(MinDistance))
    452                       < MYEPSILON) && (h < MinDistance))
    453                     {
    454                       // throw out point
    455                       //*out << Verbose(1) << "Throwing out " << *runner->second.second << "." << endl;
    456                       BoundaryPoints[axis].erase(runner);
    457                       flag = true;
    458                     }
    459                 }
    460             }
    461         }
    462       while (flag);
    463     }
    464   return BoundaryPoints;
     272        atom *Walker = NULL;
     273        PointMap PointsOnBoundary;
     274        LineMap LinesOnBoundary;
     275        TriangleMap TrianglesOnBoundary;
     276
     277        *out << Verbose(1) << "Finding all boundary points." << endl;
     278        Boundaries *BoundaryPoints = new Boundaries[NDIM]; // first is alpha, second is (r, nr)
     279        BoundariesTestPair BoundaryTestPair;
     280        Vector AxisVector, AngleReferenceVector, AngleReferenceNormalVector;
     281        double radius, angle;
     282        // 3a. Go through every axis
     283        for (int axis = 0; axis < NDIM; axis++)
     284                {
     285                        AxisVector.Zero();
     286                        AngleReferenceVector.Zero();
     287                        AngleReferenceNormalVector.Zero();
     288                        AxisVector.x[axis] = 1.;
     289                        AngleReferenceVector.x[(axis + 1) % NDIM] = 1.;
     290                        AngleReferenceNormalVector.x[(axis + 2) % NDIM] = 1.;
     291                        //              *out << Verbose(1) << "Axisvector is ";
     292                        //              AxisVector.Output(out);
     293                        //              *out << " and AngleReferenceVector is ";
     294                        //              AngleReferenceVector.Output(out);
     295                        //              *out << "." << endl;
     296                        //              *out << " and AngleReferenceNormalVector is ";
     297                        //              AngleReferenceNormalVector.Output(out);
     298                        //              *out << "." << endl;
     299                        // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours
     300                        Walker = mol->start;
     301                        while (Walker->next != mol->end)
     302                                {
     303                                        Walker = Walker->next;
     304                                        Vector ProjectedVector;
     305                                        ProjectedVector.CopyVector(&Walker->x);
     306                                        ProjectedVector.ProjectOntoPlane(&AxisVector);
     307                                        // correct for negative side
     308                                        //if (Projection(y) < 0)
     309                                        //angle = 2.*M_PI - angle;
     310                                        radius = ProjectedVector.Norm();
     311                                        if (fabs(radius) > MYEPSILON)
     312                                                angle = ProjectedVector.Angle(&AngleReferenceVector);
     313                                        else
     314                                                angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues
     315
     316                                        //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl;
     317                                        if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0)
     318                                                {
     319                                                        angle = 2. * M_PI - angle;
     320                                                }
     321                                        //*out << Verbose(2) << "Inserting " << *Walker << ": (r, alpha) = (" << radius << "," << angle << "): ";
     322                                        //ProjectedVector.Output(out);
     323                                        //*out << endl;
     324                                        BoundaryTestPair = BoundaryPoints[axis].insert(BoundariesPair(angle,
     325                                                        DistancePair (radius, Walker)));
     326                                        if (BoundaryTestPair.second)
     327                                                { // successfully inserted
     328                                                }
     329                                        else
     330                                                { // same point exists, check first r, then distance of original vectors to center of gravity
     331                                                        *out << Verbose(2)
     332                                                                        << "Encountered two vectors whose projection onto axis "
     333                                                                        << axis << " is equal: " << endl;
     334                                                        *out << Verbose(2) << "Present vector: ";
     335                                                        BoundaryTestPair.first->second.second->x.Output(out);
     336                                                        *out << endl;
     337                                                        *out << Verbose(2) << "New vector: ";
     338                                                        Walker->x.Output(out);
     339                                                        *out << endl;
     340                                                        double tmp = ProjectedVector.Norm();
     341                                                        if (tmp > BoundaryTestPair.first->second.first)
     342                                                                {
     343                                                                        BoundaryTestPair.first->second.first = tmp;
     344                                                                        BoundaryTestPair.first->second.second = Walker;
     345                                                                        *out << Verbose(2) << "Keeping new vector." << endl;
     346                                                                }
     347                                                        else if (tmp == BoundaryTestPair.first->second.first)
     348                                                                {
     349                                                                        if (BoundaryTestPair.first->second.second->x.ScalarProduct(
     350                                                                                        &BoundaryTestPair.first->second.second->x)
     351                                                                                        < Walker->x.ScalarProduct(&Walker->x))
     352                                                                                { // Norm() does a sqrt, which makes it a lot slower
     353                                                                                        BoundaryTestPair.first->second.second = Walker;
     354                                                                                        *out << Verbose(2) << "Keeping new vector." << endl;
     355                                                                                }
     356                                                                        else
     357                                                                                {
     358                                                                                        *out << Verbose(2) << "Keeping present vector." << endl;
     359                                                                                }
     360                                                                }
     361                                                        else
     362                                                                {
     363                                                                        *out << Verbose(2) << "Keeping present vector." << endl;
     364                                                                }
     365                                                }
     366                                }
     367                        // printing all inserted for debugging
     368                        //              {
     369                        //                      *out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl;
     370                        //                      int i=0;
     371                        //                      for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
     372                        //                              if (runner != BoundaryPoints[axis].begin())
     373                        //                                      *out << ", " << i << ": " << *runner->second.second;
     374                        //                              else
     375                        //                                      *out << i << ": " << *runner->second.second;
     376                        //                              i++;
     377                        //                      }
     378                        //                      *out << endl;
     379                        //              }
     380                        // 3c. throw out points whose distance is less than the mean of left and right neighbours
     381                        bool flag = false;
     382                        do
     383                                { // do as long as we still throw one out per round
     384                                        *out << Verbose(1)
     385                                                        << "Looking for candidates to kick out by convex condition ... "
     386                                                        << endl;
     387                                        flag = false;
     388                                        Boundaries::iterator left = BoundaryPoints[axis].end();
     389                                        Boundaries::iterator right = BoundaryPoints[axis].end();
     390                                        for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner
     391                                                        != BoundaryPoints[axis].end(); runner++)
     392                                                {
     393                                                        // set neighbours correctly
     394                                                        if (runner == BoundaryPoints[axis].begin())
     395                                                                {
     396                                                                        left = BoundaryPoints[axis].end();
     397                                                                }
     398                                                        else
     399                                                                {
     400                                                                        left = runner;
     401                                                                }
     402                                                        left--;
     403                                                        right = runner;
     404                                                        right++;
     405                                                        if (right == BoundaryPoints[axis].end())
     406                                                                {
     407                                                                        right = BoundaryPoints[axis].begin();
     408                                                                }
     409                                                        // check distance
     410
     411                                                        // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector)
     412                                                                {
     413                                                                        Vector SideA, SideB, SideC, SideH;
     414                                                                        SideA.CopyVector(&left->second.second->x);
     415                                                                        SideA.ProjectOntoPlane(&AxisVector);
     416                                                                        //                                      *out << "SideA: ";
     417                                                                        //                                      SideA.Output(out);
     418                                                                        //                                      *out << endl;
     419
     420                                                                        SideB.CopyVector(&right->second.second->x);
     421                                                                        SideB.ProjectOntoPlane(&AxisVector);
     422                                                                        //                                      *out << "SideB: ";
     423                                                                        //                                      SideB.Output(out);
     424                                                                        //                                      *out << endl;
     425
     426                                                                        SideC.CopyVector(&left->second.second->x);
     427                                                                        SideC.SubtractVector(&right->second.second->x);
     428                                                                        SideC.ProjectOntoPlane(&AxisVector);
     429                                                                        //                                      *out << "SideC: ";
     430                                                                        //                                      SideC.Output(out);
     431                                                                        //                                      *out << endl;
     432
     433                                                                        SideH.CopyVector(&runner->second.second->x);
     434                                                                        SideH.ProjectOntoPlane(&AxisVector);
     435                                                                        //                                      *out << "SideH: ";
     436                                                                        //                                      SideH.Output(out);
     437                                                                        //                                      *out << endl;
     438
     439                                                                        // calculate each length
     440                                                                        double a = SideA.Norm();
     441                                                                        //double b = SideB.Norm();
     442                                                                        //double c = SideC.Norm();
     443                                                                        double h = SideH.Norm();
     444                                                                        // calculate the angles
     445                                                                        double alpha = SideA.Angle(&SideH);
     446                                                                        double beta = SideA.Angle(&SideC);
     447                                                                        double gamma = SideB.Angle(&SideH);
     448                                                                        double delta = SideC.Angle(&SideH);
     449                                                                        double MinDistance = a * sin(beta) / (sin(delta)) * (((alpha
     450                                                                                        < M_PI / 2.) || (gamma < M_PI / 2.)) ? 1. : -1.);
     451                                                                        //                                      *out << Verbose(2) << " I calculated: a = " << a << ", h = " << h << ", beta(" << left->second.second->Name << "," << left->second.second->Name << "-" << right->second.second->Name << ") = " << beta << ", delta(" << left->second.second->Name << "," << runner->second.second->Name << ") = " << delta << ", Min = " << MinDistance << "." << endl;
     452                                                                        //*out << Verbose(1) << "Checking CoG distance of runner " << *runner->second.second << " " << h << " against triangle's side length spanned by (" << *left->second.second << "," << *right->second.second << ") of " << MinDistance << "." << endl;
     453                                                                        if ((fabs(h / fabs(h) - MinDistance / fabs(MinDistance))
     454                                                                                        < MYEPSILON) && (h < MinDistance))
     455                                                                                {
     456                                                                                        // throw out point
     457                                                                                        //*out << Verbose(1) << "Throwing out " << *runner->second.second << "." << endl;
     458                                                                                        BoundaryPoints[axis].erase(runner);
     459                                                                                        flag = true;
     460                                                                                }
     461                                                                }
     462                                                }
     463                                }
     464                        while (flag);
     465                }
     466        return BoundaryPoints;
    465467}
    466468;
     
    476478double *
    477479GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol,
    478     bool IsAngstroem)
    479 {
    480   // get points on boundary of NULL was given as parameter
    481   bool BoundaryFreeFlag = false;
    482   Boundaries *BoundaryPoints = BoundaryPtr;
    483   if (BoundaryPoints == NULL)
    484     {
    485       BoundaryFreeFlag = true;
    486       BoundaryPoints = GetBoundaryPoints(out, mol);
    487     }
    488   else
    489     {
    490       *out << Verbose(1) << "Using given boundary points set." << endl;
    491     }
    492   // determine biggest "diameter" of cluster for each axis
    493   Boundaries::iterator Neighbour, OtherNeighbour;
    494   double *GreatestDiameter = new double[NDIM];
    495   for (int i = 0; i < NDIM; i++)
    496     GreatestDiameter[i] = 0.;
    497   double OldComponent, tmp, w1, w2;
    498   Vector DistanceVector, OtherVector;
    499   int component, Othercomponent;
    500   for (int axis = 0; axis < NDIM; axis++)
    501     { // regard each projected plane
    502       //*out << Verbose(1) << "Current axis is " << axis << "." << endl;
    503       for (int j = 0; j < 2; j++)
    504         { // and for both axis on the current plane
    505           component = (axis + j + 1) % NDIM;
    506           Othercomponent = (axis + 1 + ((j + 1) & 1)) % NDIM;
    507           //*out << Verbose(1) << "Current component is " << component << ", Othercomponent is " << Othercomponent << "." << endl;
    508           for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner
    509               != BoundaryPoints[axis].end(); runner++)
    510             {
    511               //*out << Verbose(2) << "Current runner is " << *(runner->second.second) << "." << endl;
    512               // seek for the neighbours pair where the Othercomponent sign flips
    513               Neighbour = runner;
    514               Neighbour++;
    515               if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around
    516                 Neighbour = BoundaryPoints[axis].begin();
    517               DistanceVector.CopyVector(&runner->second.second->x);
    518               DistanceVector.SubtractVector(&Neighbour->second.second->x);
    519               do
    520                 { // seek for neighbour pair where it flips
    521                   OldComponent = DistanceVector.x[Othercomponent];
    522                   Neighbour++;
    523                   if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around
    524                     Neighbour = BoundaryPoints[axis].begin();
    525                   DistanceVector.CopyVector(&runner->second.second->x);
    526                   DistanceVector.SubtractVector(&Neighbour->second.second->x);
    527                   //*out << Verbose(3) << "OldComponent is " << OldComponent << ", new one is " << DistanceVector.x[Othercomponent] << "." << endl;
    528                 }
    529               while ((runner != Neighbour) && (fabs(OldComponent / fabs(
    530                   OldComponent) - DistanceVector.x[Othercomponent] / fabs(
    531                   DistanceVector.x[Othercomponent])) < MYEPSILON)); // as long as sign does not flip
    532               if (runner != Neighbour)
    533                 {
    534                   OtherNeighbour = Neighbour;
    535                   if (OtherNeighbour == BoundaryPoints[axis].begin()) // make it wrap around
    536                     OtherNeighbour = BoundaryPoints[axis].end();
    537                   OtherNeighbour--;
    538                   //*out << Verbose(2) << "The pair, where the sign of OtherComponent flips, is: " << *(Neighbour->second.second) << " and " << *(OtherNeighbour->second.second) << "." << endl;
    539                   // now we have found the pair: Neighbour and OtherNeighbour
    540                   OtherVector.CopyVector(&runner->second.second->x);
    541                   OtherVector.SubtractVector(&OtherNeighbour->second.second->x);
    542                   //*out << Verbose(2) << "Distances to Neighbour and OtherNeighbour are " << DistanceVector.x[component] << " and " << OtherVector.x[component] << "." << endl;
    543                   //*out << Verbose(2) << "OtherComponents to Neighbour and OtherNeighbour are " << DistanceVector.x[Othercomponent] << " and " << OtherVector.x[Othercomponent] << "." << endl;
    544                   // do linear interpolation between points (is exact) to extract exact intersection between Neighbour and OtherNeighbour
    545                   w1 = fabs(OtherVector.x[Othercomponent]);
    546                   w2 = fabs(DistanceVector.x[Othercomponent]);
    547                   tmp = fabs((w1 * DistanceVector.x[component] + w2
    548                       * OtherVector.x[component]) / (w1 + w2));
    549                   // mark if it has greater diameter
    550                   //*out << Verbose(2) << "Comparing current greatest " << GreatestDiameter[component] << " to new " << tmp << "." << endl;
    551                   GreatestDiameter[component] = (GreatestDiameter[component]
    552                       > tmp) ? GreatestDiameter[component] : tmp;
    553                 } //else
    554               //*out << Verbose(2) << "Saw no sign flip, probably top or bottom node." << endl;
    555             }
    556         }
    557     }
    558   *out << Verbose(0) << "RESULT: The biggest diameters are "
    559       << GreatestDiameter[0] << " and " << GreatestDiameter[1] << " and "
    560       << GreatestDiameter[2] << " " << (IsAngstroem ? "angstrom"
    561       : "atomiclength") << "." << endl;
    562 
    563   // free reference lists
    564   if (BoundaryFreeFlag)
    565     delete[] (BoundaryPoints);
    566 
    567   return GreatestDiameter;
    568 }
    569 ;
    570 
    571 /** Creates the objects in a raster3d file (renderable with a header.r3d)
     480                bool IsAngstroem)
     481{
     482        // get points on boundary of NULL was given as parameter
     483        bool BoundaryFreeFlag = false;
     484        Boundaries *BoundaryPoints = BoundaryPtr;
     485        if (BoundaryPoints == NULL)
     486                {
     487                        BoundaryFreeFlag = true;
     488                        BoundaryPoints = GetBoundaryPoints(out, mol);
     489                }
     490        else
     491                {
     492                        *out << Verbose(1) << "Using given boundary points set." << endl;
     493                }
     494        // determine biggest "diameter" of cluster for each axis
     495        Boundaries::iterator Neighbour, OtherNeighbour;
     496        double *GreatestDiameter = new double[NDIM];
     497        for (int i = 0; i < NDIM; i++)
     498                GreatestDiameter[i] = 0.;
     499        double OldComponent, tmp, w1, w2;
     500        Vector DistanceVector, OtherVector;
     501        int component, Othercomponent;
     502        for (int axis = 0; axis < NDIM; axis++)
     503                { // regard each projected plane
     504                        //*out << Verbose(1) << "Current axis is " << axis << "." << endl;
     505                        for (int j = 0; j < 2; j++)
     506                                { // and for both axis on the current plane
     507                                        component = (axis + j + 1) % NDIM;
     508                                        Othercomponent = (axis + 1 + ((j + 1) & 1)) % NDIM;
     509                                        //*out << Verbose(1) << "Current component is " << component << ", Othercomponent is " << Othercomponent << "." << endl;
     510                                        for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner
     511                                                        != BoundaryPoints[axis].end(); runner++)
     512                                                {
     513                                                        //*out << Verbose(2) << "Current runner is " << *(runner->second.second) << "." << endl;
     514                                                        // seek for the neighbours pair where the Othercomponent sign flips
     515                                                        Neighbour = runner;
     516                                                        Neighbour++;
     517                                                        if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around
     518                                                                Neighbour = BoundaryPoints[axis].begin();
     519                                                        DistanceVector.CopyVector(&runner->second.second->x);
     520                                                        DistanceVector.SubtractVector(&Neighbour->second.second->x);
     521                                                        do
     522                                                                { // seek for neighbour pair where it flips
     523                                                                        OldComponent = DistanceVector.x[Othercomponent];
     524                                                                        Neighbour++;
     525                                                                        if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around
     526                                                                                Neighbour = BoundaryPoints[axis].begin();
     527                                                                        DistanceVector.CopyVector(&runner->second.second->x);
     528                                                                        DistanceVector.SubtractVector(&Neighbour->second.second->x);
     529                                                                        //*out << Verbose(3) << "OldComponent is " << OldComponent << ", new one is " << DistanceVector.x[Othercomponent] << "." << endl;
     530                                                                }
     531                                                        while ((runner != Neighbour) && (fabs(OldComponent / fabs(
     532                                                                        OldComponent) - DistanceVector.x[Othercomponent] / fabs(
     533                                                                        DistanceVector.x[Othercomponent])) < MYEPSILON)); // as long as sign does not flip
     534                                                        if (runner != Neighbour)
     535                                                                {
     536                                                                        OtherNeighbour = Neighbour;
     537                                                                        if (OtherNeighbour == BoundaryPoints[axis].begin()) // make it wrap around
     538                                                                                OtherNeighbour = BoundaryPoints[axis].end();
     539                                                                        OtherNeighbour--;
     540                                                                        //*out << Verbose(2) << "The pair, where the sign of OtherComponent flips, is: " << *(Neighbour->second.second) << " and " << *(OtherNeighbour->second.second) << "." << endl;
     541                                                                        // now we have found the pair: Neighbour and OtherNeighbour
     542                                                                        OtherVector.CopyVector(&runner->second.second->x);
     543                                                                        OtherVector.SubtractVector(&OtherNeighbour->second.second->x);
     544                                                                        //*out << Verbose(2) << "Distances to Neighbour and OtherNeighbour are " << DistanceVector.x[component] << " and " << OtherVector.x[component] << "." << endl;
     545                                                                        //*out << Verbose(2) << "OtherComponents to Neighbour and OtherNeighbour are " << DistanceVector.x[Othercomponent] << " and " << OtherVector.x[Othercomponent] << "." << endl;
     546                                                                        // do linear interpolation between points (is exact) to extract exact intersection between Neighbour and OtherNeighbour
     547                                                                        w1 = fabs(OtherVector.x[Othercomponent]);
     548                                                                        w2 = fabs(DistanceVector.x[Othercomponent]);
     549                                                                        tmp = fabs((w1 * DistanceVector.x[component] + w2
     550                                                                                        * OtherVector.x[component]) / (w1 + w2));
     551                                                                        // mark if it has greater diameter
     552                                                                        //*out << Verbose(2) << "Comparing current greatest " << GreatestDiameter[component] << " to new " << tmp << "." << endl;
     553                                                                        GreatestDiameter[component] = (GreatestDiameter[component]
     554                                                                                        > tmp) ? GreatestDiameter[component] : tmp;
     555                                                                } //else
     556                                                        //*out << Verbose(2) << "Saw no sign flip, probably top or bottom node." << endl;
     557                                                }
     558                                }
     559                }
     560        *out << Verbose(0) << "RESULT: The biggest diameters are "
     561                        << GreatestDiameter[0] << " and " << GreatestDiameter[1] << " and "
     562                        << GreatestDiameter[2] << " " << (IsAngstroem ? "angstrom"
     563                        : "atomiclength") << "." << endl;
     564
     565        // free reference lists
     566        if (BoundaryFreeFlag)
     567                delete[] (BoundaryPoints);
     568
     569        return GreatestDiameter;
     570}
     571;
     572
     573/** Creates the objects in a VRML file.
    572574 * \param *out output stream for debugging
    573  * \param *tecplot output stream for tecplot data
     575 * \param *vrmlfile output stream for tecplot data
     576 * \param *Tess Tesselation structure with constructed triangles
     577 * \param *mol molecule structure with atom positions
     578 */
     579void write_vrml_file(ofstream *out, ofstream *vrmlfile, class Tesselation *Tess, class molecule *mol)
     580{
     581        atom *Walker = mol->start;
     582        bond *Binder = mol->first;
     583        int i;
     584        Vector *center = mol->DetermineCenterOfAll(out);
     585        if (vrmlfile != NULL) {
     586                //cout << Verbose(1) << "Writing Raster3D file ... ";
     587                *vrmlfile << "#VRML V2.0 utf8" << endl;
     588                *vrmlfile << "#Created by molecuilder" << endl;
     589                *vrmlfile << "#All atoms as spheres" << endl;
     590                while (Walker->next != mol->end) {
     591                        Walker = Walker->next;
     592                        *vrmlfile << "Sphere {" << endl << "    "; // 2 is sphere type
     593                        for (i=0;i<NDIM;i++)
     594                                *vrmlfile << Walker->x.x[i]+center->x[i] << " ";
     595                        *vrmlfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour
     596                }
     597
     598                *vrmlfile << "# All bonds as vertices" << endl;
     599                while (Binder->next != mol->last) {
     600                        Binder = Binder->next;
     601                        *vrmlfile << "3" << endl << "   "; // 2 is round-ended cylinder type
     602                        for (i=0;i<NDIM;i++)
     603                                *vrmlfile << Binder->leftatom->x.x[i]+center->x[i] << " ";
     604                        *vrmlfile << "\t0.03\t";
     605                        for (i=0;i<NDIM;i++)
     606                                *vrmlfile << Binder->rightatom->x.x[i]+center->x[i] << " ";
     607                        *vrmlfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour
     608                }
     609
     610                *vrmlfile << "# All tesselation triangles" << endl;
     611                for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) {
     612                        *vrmlfile << "1" << endl << "   "; // 1 is triangle type
     613                        for (i=0;i<3;i++) { // print each node
     614                                for (int j=0;j<NDIM;j++)        // and for each node all NDIM coordinates
     615                                        *vrmlfile << TriangleRunner->second->endpoints[i]->node->x.x[j]+center->x[j] << " ";
     616                                *vrmlfile << "\t";
     617                        }
     618                        *vrmlfile << "1. 0. 0." << endl;        // red as colour
     619                        *vrmlfile << "18" << endl << "  0.5 0.5 0.5" << endl; // 18 is transparency type for previous object
     620                }
     621        } else {
     622                cerr << "ERROR: Given vrmlfile is " << vrmlfile << "." << endl;
     623        }
     624        delete(center);
     625};
     626
     627/** Creates the objects in a raster3d file (renderable with a header.r3d).
     628 * \param *out output stream for debugging
     629 * \param *rasterfile output stream for tecplot data
    574630 * \param *Tess Tesselation structure with constructed triangles
    575631 * \param *mol molecule structure with atom positions
     
    577633void write_raster3d_file(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, class molecule *mol)
    578634{
    579   atom *Walker = mol->start;
    580   bond *Binder = mol->first;
    581   int i;
    582   Vector *center = mol->DetermineCenterOfAll(out);
    583   if (rasterfile != NULL) {
    584     //cout << Verbose(1) << "Writing Raster3D file ... ";
    585     *rasterfile << "# Raster3D object description, created by MoleCuilder" << endl;
    586     *rasterfile << "@header.r3d" << endl;
    587     *rasterfile << "# All atoms as spheres" << endl;
    588     while (Walker->next != mol->end) {
    589       Walker = Walker->next;
    590       *rasterfile << "2" << endl << "  "; // 2 is sphere type
    591       for (i=0;i<NDIM;i++)
    592         *rasterfile << Walker->x.x[i]+center->x[i] << " ";
    593       *rasterfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour
    594     }
    595 
    596     *rasterfile << "# All bonds as vertices" << endl;
    597     while (Binder->next != mol->last) {
    598       Binder = Binder->next;
    599       *rasterfile << "3" << endl << "  "; // 2 is round-ended cylinder type
    600       for (i=0;i<NDIM;i++)
    601         *rasterfile << Binder->leftatom->x.x[i]+center->x[i] << " ";
    602       *rasterfile << "\t0.03\t";
    603       for (i=0;i<NDIM;i++)
    604         *rasterfile << Binder->rightatom->x.x[i]+center->x[i] << " ";
    605       *rasterfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour
    606     }
    607 
    608     *rasterfile << "# All tesselation triangles" << endl;
    609     for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) {
    610       *rasterfile << "1" << endl << "  "; // 1 is triangle type
    611       for (i=0;i<3;i++) { // print each node
    612         for (int j=0;j<NDIM;j++)  // and for each node all NDIM coordinates
    613           *rasterfile << TriangleRunner->second->endpoints[i]->node->x.x[j]+center->x[j] << " ";
    614         *rasterfile << "\t";
    615       }
    616       *rasterfile << "1. 0. 0." << endl;  // red as colour
    617       *rasterfile << "18" << endl << "  0.5 0.5 0.5" << endl; // 18 is transparency type for previous object
    618     }
    619   } else {
    620     cerr << "ERROR: Given rasterfile is " << rasterfile << "." << endl;
    621   }
    622   delete(center);
     635        atom *Walker = mol->start;
     636        bond *Binder = mol->first;
     637        int i;
     638        Vector *center = mol->DetermineCenterOfAll(out);
     639        if (rasterfile != NULL) {
     640                //cout << Verbose(1) << "Writing Raster3D file ... ";
     641                *rasterfile << "# Raster3D object description, created by MoleCuilder" << endl;
     642                *rasterfile << "@header.r3d" << endl;
     643                *rasterfile << "# All atoms as spheres" << endl;
     644                while (Walker->next != mol->end) {
     645                        Walker = Walker->next;
     646                        *rasterfile << "2" << endl << " ";      // 2 is sphere type
     647                        for (i=0;i<NDIM;i++)
     648                                *rasterfile << Walker->x.x[i]+center->x[i] << " ";
     649                        *rasterfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour
     650                }
     651
     652                *rasterfile << "# All bonds as vertices" << endl;
     653                while (Binder->next != mol->last) {
     654                        Binder = Binder->next;
     655                        *rasterfile << "3" << endl << " ";      // 2 is round-ended cylinder type
     656                        for (i=0;i<NDIM;i++)
     657                                *rasterfile << Binder->leftatom->x.x[i]+center->x[i] << " ";
     658                        *rasterfile << "\t0.03\t";
     659                        for (i=0;i<NDIM;i++)
     660                                *rasterfile << Binder->rightatom->x.x[i]+center->x[i] << " ";
     661                        *rasterfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour
     662                }
     663
     664                *rasterfile << "# All tesselation triangles" << endl;
     665                *rasterfile << "8\n     25. -1.  1. 1. 1.        0.0            0 0 0 2\n       SOLID            1.0 0.0 0.0\n  BACKFACE        0.3 0.3 1.0      0 0\n";
     666                for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) {
     667                        *rasterfile << "1" << endl << " ";      // 1 is triangle type
     668                        for (i=0;i<3;i++) {     // print each node
     669                                for (int j=0;j<NDIM;j++)        // and for each node all NDIM coordinates
     670                                        *rasterfile << TriangleRunner->second->endpoints[i]->node->x.x[j]+center->x[j] << " ";
     671                                *rasterfile << "\t";
     672                        }
     673                        *rasterfile << "1. 0. 0." << endl;      // red as colour
     674                        //*rasterfile << "18" << endl << "      0.5 0.5 0.5" << endl;   // 18 is transparency type for previous object
     675                }
     676                *rasterfile << "9\n     terminating special property\n";
     677        } else {
     678                cerr << "ERROR: Given rasterfile is " << rasterfile << "." << endl;
     679        }
     680        delete(center);
    623681};
    624682
    625 /*
    626  * This function creates the tecplot file, displaying the tesselation of the hull.
     683/** This function creates the tecplot file, displaying the tesselation of the hull.
    627684 * \param *out output stream for debugging
    628685 * \param *tecplot output stream for tecplot data
     
    631688void
    632689write_tecplot_file(ofstream *out, ofstream *tecplot,
    633     class Tesselation *TesselStruct, class molecule *mol, int N)
    634 {
    635   if (tecplot != NULL)
    636     {
    637       *tecplot << "TITLE = \"3D CONVEX SHELL\"" << endl;
    638       *tecplot << "VARIABLES = \"X\" \"Y\" \"Z\"" << endl;
    639       *tecplot << "ZONE T=\"TRIANGLES" << N << "\", N="
    640           << TesselStruct->PointsOnBoundaryCount << ", E="
    641           << TesselStruct->TrianglesOnBoundaryCount
    642           << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl;
    643       int *LookupList = new int[mol->AtomCount];
    644       for (int i = 0; i < mol->AtomCount; i++)
    645         LookupList[i] = -1;
    646 
    647       // print atom coordinates
    648       *out << Verbose(2) << "The following triangles were created:";
    649       int Counter = 1;
    650       atom *Walker = NULL;
    651       for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target
    652           != TesselStruct->PointsOnBoundary.end(); target++)
    653         {
    654           Walker = target->second->node;
    655           LookupList[Walker->nr] = Counter++;
    656           *tecplot << Walker->x.x[0] << " " << Walker->x.x[1] << " "
    657               << Walker->x.x[2] << " " << endl;
    658         }
    659       *tecplot << endl;
    660       // print connectivity
    661       for (TriangleMap::iterator runner =
    662           TesselStruct->TrianglesOnBoundary.begin(); runner
    663           != TesselStruct->TrianglesOnBoundary.end(); runner++)
    664         {
    665           *out << " " << runner->second->endpoints[0]->node->Name << "<->"
    666               << runner->second->endpoints[1]->node->Name << "<->"
    667               << runner->second->endpoints[2]->node->Name;
    668           *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " "
    669               << LookupList[runner->second->endpoints[1]->node->nr] << " "
    670               << LookupList[runner->second->endpoints[2]->node->nr] << endl;
    671         }
    672       delete[] (LookupList);
    673       *out << endl;
    674     }
     690                class Tesselation *TesselStruct, class molecule *mol, int N)
     691{
     692        if (tecplot != NULL)
     693                {
     694                        *tecplot << "TITLE = \"3D CONVEX SHELL\"" << endl;
     695                        *tecplot << "VARIABLES = \"X\" \"Y\" \"Z\"" << endl;
     696                        *tecplot << "ZONE T=\"TRIANGLES" << N << "\", N="
     697                                        << TesselStruct->PointsOnBoundaryCount << ", E="
     698                                        << TesselStruct->TrianglesOnBoundaryCount
     699                                        << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl;
     700                        int *LookupList = new int[mol->AtomCount];
     701                        for (int i = 0; i < mol->AtomCount; i++)
     702                                LookupList[i] = -1;
     703
     704                        // print atom coordinates
     705                        *out << Verbose(2) << "The following triangles were created:";
     706                        int Counter = 1;
     707                        atom *Walker = NULL;
     708                        for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target
     709                                        != TesselStruct->PointsOnBoundary.end(); target++)
     710                                {
     711                                        Walker = target->second->node;
     712                                        LookupList[Walker->nr] = Counter++;
     713                                        *tecplot << Walker->x.x[0] << " " << Walker->x.x[1] << " "
     714                                                        << Walker->x.x[2] << " " << endl;
     715                                }
     716                        *tecplot << endl;
     717                        // print connectivity
     718                        for (TriangleMap::iterator runner =
     719                                        TesselStruct->TrianglesOnBoundary.begin(); runner
     720                                        != TesselStruct->TrianglesOnBoundary.end(); runner++)
     721                                {
     722                                        *out << " " << runner->second->endpoints[0]->node->Name << "<->"
     723                                                        << runner->second->endpoints[1]->node->Name << "<->"
     724                                                        << runner->second->endpoints[2]->node->Name;
     725                                        *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " "
     726                                                        << LookupList[runner->second->endpoints[1]->node->nr] << " "
     727                                                        << LookupList[runner->second->endpoints[2]->node->nr] << endl;
     728                                }
     729                        delete[] (LookupList);
     730                        *out << endl;
     731                }
    675732}
    676733
     
    678735 * Determines first the convex envelope, then tesselates it and calculates its volume.
    679736 * \param *out output stream for debugging
    680  * \param *tecplot output stream for tecplot data
     737 * \param *filename filename prefix for output of vertex data
    681738 * \param *configuration needed for path to store convex envelope file
    682739 * \param *BoundaryPoints NDIM set of boundary points on the projected plane per axis, on return if desired
     
    685742 */
    686743double
    687 VolumeOfConvexEnvelope(ofstream *out, ofstream *tecplot, config *configuration,
    688     Boundaries *BoundaryPtr, molecule *mol)
    689 {
    690   bool IsAngstroem = configuration->GetIsAngstroem();
    691   atom *Walker = NULL;
    692   struct Tesselation *TesselStruct = new Tesselation;
    693   bool BoundaryFreeFlag = false;
    694   Boundaries *BoundaryPoints = BoundaryPtr;
    695   double volume = 0.;
    696   double PyramidVolume = 0.;
    697   double G, h;
    698   Vector x, y;
    699   double a, b, c;
    700 
    701   //Find_non_convex_border(out, tecplot, *TesselStruct, mol); // Is now called from command line.
    702 
    703   // 1. calculate center of gravity
    704   *out << endl;
    705   Vector *CenterOfGravity = mol->DetermineCenterOfGravity(out);
    706 
    707   // 2. translate all points into CoG
    708   *out << Verbose(1) << "Translating system to Center of Gravity." << endl;
    709   Walker = mol->start;
    710   while (Walker->next != mol->end)
    711     {
    712       Walker = Walker->next;
    713       Walker->x.Translate(CenterOfGravity);
    714     }
    715 
    716   // 3. Find all points on the boundary
    717   if (BoundaryPoints == NULL)
    718     {
    719       BoundaryFreeFlag = true;
    720       BoundaryPoints = GetBoundaryPoints(out, mol);
    721     }
    722   else
    723     {
    724       *out << Verbose(1) << "Using given boundary points set." << endl;
    725     }
    726 
    727   // 4. fill the boundary point list
    728   for (int axis = 0; axis < NDIM; axis++)
    729     for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner
    730         != BoundaryPoints[axis].end(); runner++)
    731       {
    732         TesselStruct->AddPoint(runner->second.second);
    733       }
    734 
    735   *out << Verbose(2) << "I found " << TesselStruct->PointsOnBoundaryCount
    736       << " points on the convex boundary." << endl;
    737   // now we have the whole set of edge points in the BoundaryList
    738 
    739   // listing for debugging
    740   //  *out << Verbose(1) << "Listing PointsOnBoundary:";
    741   //  for(PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) {
    742   //    *out << " " << *runner->second;
    743   //  }
    744   //  *out << endl;
    745 
    746   // 5a. guess starting triangle
    747   TesselStruct->GuessStartingTriangle(out);
    748 
    749   // 5b. go through all lines, that are not yet part of two triangles (only of one so far)
    750   TesselStruct->TesselateOnBoundary(out, configuration, mol);
    751 
    752   *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundaryCount
    753       << " triangles with " << TesselStruct->LinesOnBoundaryCount
    754       << " lines and " << TesselStruct->PointsOnBoundaryCount << " points."
    755       << endl;
    756 
    757   // 6a. Every triangle forms a pyramid with the center of gravity as its peak, sum up the volumes
    758   *out << Verbose(1)
    759       << "Calculating the volume of the pyramids formed out of triangles and center of gravity."
    760       << endl;
    761   for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner
    762       != TesselStruct->TrianglesOnBoundary.end(); runner++)
    763     { // go through every triangle, calculate volume of its pyramid with CoG as peak
    764       x.CopyVector(&runner->second->endpoints[0]->node->x);
    765       x.SubtractVector(&runner->second->endpoints[1]->node->x);
    766       y.CopyVector(&runner->second->endpoints[0]->node->x);
    767       y.SubtractVector(&runner->second->endpoints[2]->node->x);
    768       a = sqrt(runner->second->endpoints[0]->node->x.Distance(
    769           &runner->second->endpoints[1]->node->x));
    770       b = sqrt(runner->second->endpoints[0]->node->x.Distance(
    771           &runner->second->endpoints[2]->node->x));
    772       c = sqrt(runner->second->endpoints[2]->node->x.Distance(
    773           &runner->second->endpoints[1]->node->x));
    774       G = sqrt(((a * a + b * b + c * c) * (a * a + b * b + c * c) - 2 * (a * a
    775           * a * a + b * b * b * b + c * c * c * c)) / 16.); // area of tesselated triangle
    776       x.MakeNormalVector(&runner->second->endpoints[0]->node->x,
    777           &runner->second->endpoints[1]->node->x,
    778           &runner->second->endpoints[2]->node->x);
    779       x.Scale(runner->second->endpoints[1]->node->x.Projection(&x));
    780       h = x.Norm(); // distance of CoG to triangle
    781       PyramidVolume = (1. / 3.) * G * h; // this formula holds for _all_ pyramids (independent of n-edge base or (not) centered peak)
    782       *out << Verbose(2) << "Area of triangle is " << G << " "
    783           << (IsAngstroem ? "angstrom" : "atomiclength") << "^2, height is "
    784           << h << " and the volume is " << PyramidVolume << " "
    785           << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
    786       volume += PyramidVolume;
    787     }
    788   *out << Verbose(0) << "RESULT: The summed volume is " << setprecision(10)
    789       << volume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3."
    790       << endl;
    791 
    792   // 7. translate all points back from CoG
    793   *out << Verbose(1) << "Translating system back from Center of Gravity."
    794       << endl;
    795   CenterOfGravity->Scale(-1);
    796   Walker = mol->start;
    797   while (Walker->next != mol->end)
    798     {
    799       Walker = Walker->next;
    800       Walker->x.Translate(CenterOfGravity);
    801     }
    802 
    803   // 8. Store triangles in tecplot file
    804   write_tecplot_file(out, tecplot, TesselStruct, mol, 0);
    805 
    806   // free reference lists
    807   if (BoundaryFreeFlag)
    808     delete[] (BoundaryPoints);
    809 
    810   return volume;
     744VolumeOfConvexEnvelope(ofstream *out, const char *filename, config *configuration,
     745                Boundaries *BoundaryPtr, molecule *mol)
     746{
     747        bool IsAngstroem = configuration->GetIsAngstroem();
     748        atom *Walker = NULL;
     749        struct Tesselation *TesselStruct = new Tesselation;
     750        bool BoundaryFreeFlag = false;
     751        Boundaries *BoundaryPoints = BoundaryPtr;
     752        double volume = 0.;
     753        double PyramidVolume = 0.;
     754        double G, h;
     755        Vector x, y;
     756        double a, b, c;
     757
     758        //Find_non_convex_border(out, tecplot, *TesselStruct, mol); // Is now called from command line.
     759
     760        // 1. calculate center of gravity
     761        *out << endl;
     762        Vector *CenterOfGravity = mol->DetermineCenterOfGravity(out);
     763
     764        // 2. translate all points into CoG
     765        *out << Verbose(1) << "Translating system to Center of Gravity." << endl;
     766        Walker = mol->start;
     767        while (Walker->next != mol->end)
     768                {
     769                        Walker = Walker->next;
     770                        Walker->x.Translate(CenterOfGravity);
     771                }
     772
     773        // 3. Find all points on the boundary
     774        if (BoundaryPoints == NULL)
     775                {
     776                        BoundaryFreeFlag = true;
     777                        BoundaryPoints = GetBoundaryPoints(out, mol);
     778                }
     779        else
     780                {
     781                        *out << Verbose(1) << "Using given boundary points set." << endl;
     782                }
     783
     784        // 4. fill the boundary point list
     785        for (int axis = 0; axis < NDIM; axis++)
     786                for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner
     787                                != BoundaryPoints[axis].end(); runner++)
     788                        {
     789                                TesselStruct->AddPoint(runner->second.second);
     790                        }
     791
     792        *out << Verbose(2) << "I found " << TesselStruct->PointsOnBoundaryCount
     793                        << " points on the convex boundary." << endl;
     794        // now we have the whole set of edge points in the BoundaryList
     795
     796        // listing for debugging
     797        //      *out << Verbose(1) << "Listing PointsOnBoundary:";
     798        //      for(PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) {
     799        //              *out << " " << *runner->second;
     800        //      }
     801        //      *out << endl;
     802
     803        // 5a. guess starting triangle
     804        TesselStruct->GuessStartingTriangle(out);
     805
     806        // 5b. go through all lines, that are not yet part of two triangles (only of one so far)
     807        TesselStruct->TesselateOnBoundary(out, configuration, mol);
     808
     809        *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundaryCount
     810                        << " triangles with " << TesselStruct->LinesOnBoundaryCount
     811                        << " lines and " << TesselStruct->PointsOnBoundaryCount << " points."
     812                        << endl;
     813
     814        // 6a. Every triangle forms a pyramid with the center of gravity as its peak, sum up the volumes
     815        *out << Verbose(1)
     816                        << "Calculating the volume of the pyramids formed out of triangles and center of gravity."
     817                        << endl;
     818        for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner
     819                        != TesselStruct->TrianglesOnBoundary.end(); runner++)
     820                { // go through every triangle, calculate volume of its pyramid with CoG as peak
     821                        x.CopyVector(&runner->second->endpoints[0]->node->x);
     822                        x.SubtractVector(&runner->second->endpoints[1]->node->x);
     823                        y.CopyVector(&runner->second->endpoints[0]->node->x);
     824                        y.SubtractVector(&runner->second->endpoints[2]->node->x);
     825                        a = sqrt(runner->second->endpoints[0]->node->x.DistanceSquared(
     826                                        &runner->second->endpoints[1]->node->x));
     827                        b = sqrt(runner->second->endpoints[0]->node->x.DistanceSquared(
     828                                        &runner->second->endpoints[2]->node->x));
     829                        c = sqrt(runner->second->endpoints[2]->node->x.DistanceSquared(
     830                                        &runner->second->endpoints[1]->node->x));
     831                        G = sqrt(((a + b + c) * (a + b + c) - 2 * (a * a + b * b + c * c)) / 16.); // area of tesselated triangle
     832                        x.MakeNormalVector(&runner->second->endpoints[0]->node->x,
     833                                        &runner->second->endpoints[1]->node->x,
     834                                        &runner->second->endpoints[2]->node->x);
     835                        x.Scale(runner->second->endpoints[1]->node->x.Projection(&x));
     836                        h = x.Norm(); // distance of CoG to triangle
     837                        PyramidVolume = (1. / 3.) * G * h; // this formula holds for _all_ pyramids (independent of n-edge base or (not) centered peak)
     838                        *out << Verbose(2) << "Area of triangle is " << G << " "
     839                                        << (IsAngstroem ? "angstrom" : "atomiclength") << "^2, height is "
     840                                        << h << " and the volume is " << PyramidVolume << " "
     841                                        << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
     842                        volume += PyramidVolume;
     843                }
     844        *out << Verbose(0) << "RESULT: The summed volume is " << setprecision(10)
     845                        << volume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3."
     846                        << endl;
     847
     848        // 7. translate all points back from CoG
     849        *out << Verbose(1) << "Translating system back from Center of Gravity."
     850                        << endl;
     851        CenterOfGravity->Scale(-1);
     852        Walker = mol->start;
     853        while (Walker->next != mol->end)
     854                {
     855                        Walker = Walker->next;
     856                        Walker->x.Translate(CenterOfGravity);
     857                }
     858
     859        // 8. Store triangles in tecplot file
     860        string OutputName(filename);
     861        OutputName.append(TecplotSuffix);
     862        ofstream *tecplot = new ofstream(OutputName.c_str());
     863        write_tecplot_file(out, tecplot, TesselStruct, mol, 0);
     864        tecplot->close();
     865        delete(tecplot);
     866
     867        // free reference lists
     868        if (BoundaryFreeFlag)
     869                delete[] (BoundaryPoints);
     870
     871        return volume;
    811872}
    812873;
     
    822883void
    823884PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol,
    824     double ClusterVolume, double celldensity)
    825 {
    826   // transform to PAS
    827   mol->PrincipalAxisSystem(out, true);
    828 
    829   // some preparations beforehand
    830   bool IsAngstroem = configuration->GetIsAngstroem();
    831   Boundaries *BoundaryPoints = GetBoundaryPoints(out, mol);
    832   double clustervolume;
    833   if (ClusterVolume == 0)
    834     clustervolume = VolumeOfConvexEnvelope(out, NULL, configuration,
    835         BoundaryPoints, mol);
    836   else
    837     clustervolume = ClusterVolume;
    838   double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol,
    839       IsAngstroem);
    840   Vector BoxLengths;
    841   int repetition[NDIM] =
    842     { 1, 1, 1 };
    843   int TotalNoClusters = 1;
    844   for (int i = 0; i < NDIM; i++)
    845     TotalNoClusters *= repetition[i];
    846 
    847   // sum up the atomic masses
    848   double totalmass = 0.;
    849   atom *Walker = mol->start;
    850   while (Walker->next != mol->end)
    851     {
    852       Walker = Walker->next;
    853       totalmass += Walker->type->mass;
    854     }
    855   *out << Verbose(0) << "RESULT: The summed mass is " << setprecision(10)
    856       << totalmass << " atomicmassunit." << endl;
    857 
    858   *out << Verbose(0) << "RESULT: The average density is " << setprecision(10)
    859       << totalmass / clustervolume << " atomicmassunit/"
    860       << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
    861 
    862   // solve cubic polynomial
    863   *out << Verbose(1) << "Solving equidistant suspension in water problem ..."
    864       << endl;
    865   double cellvolume;
    866   if (IsAngstroem)
    867     cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_A - (totalmass
    868         / clustervolume)) / (celldensity - 1);
    869   else
    870     cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_a0 - (totalmass
    871         / clustervolume)) / (celldensity - 1);
    872   *out << Verbose(1) << "Cellvolume needed for a density of " << celldensity
    873       << " g/cm^3 is " << cellvolume << " " << (IsAngstroem ? "angstrom"
    874       : "atomiclength") << "^3." << endl;
    875 
    876   double minimumvolume = TotalNoClusters * (GreatestDiameter[0]
    877       * GreatestDiameter[1] * GreatestDiameter[2]);
    878   *out << Verbose(1)
    879       << "Minimum volume of the convex envelope contained in a rectangular box is "
    880       << minimumvolume << " atomicmassunit/" << (IsAngstroem ? "angstrom"
    881       : "atomiclength") << "^3." << endl;
    882   if (minimumvolume > cellvolume)
    883     {
    884       cerr << Verbose(0)
    885           << "ERROR: the containing box already has a greater volume than the envisaged cell volume!"
    886           << endl;
    887       cout << Verbose(0)
    888           << "Setting Box dimensions to minimum possible, the greatest diameters."
    889           << endl;
    890       for (int i = 0; i < NDIM; i++)
    891         BoxLengths.x[i] = GreatestDiameter[i];
    892       mol->CenterEdge(out, &BoxLengths);
    893     }
    894   else
    895     {
    896       BoxLengths.x[0] = (repetition[0] * GreatestDiameter[0] + repetition[1]
    897           * GreatestDiameter[1] + repetition[2] * GreatestDiameter[2]);
    898       BoxLengths.x[1] = (repetition[0] * repetition[1] * GreatestDiameter[0]
    899           * GreatestDiameter[1] + repetition[0] * repetition[2]
    900           * GreatestDiameter[0] * GreatestDiameter[2] + repetition[1]
    901           * repetition[2] * GreatestDiameter[1] * GreatestDiameter[2]);
    902       BoxLengths.x[2] = minimumvolume - cellvolume;
    903       double x0 = 0., x1 = 0., x2 = 0.;
    904       if (gsl_poly_solve_cubic(BoxLengths.x[0], BoxLengths.x[1],
    905           BoxLengths.x[2], &x0, &x1, &x2) == 1) // either 1 or 3 on return
    906         *out << Verbose(0) << "RESULT: The resulting spacing is: " << x0
    907             << " ." << endl;
    908       else
    909         {
    910           *out << Verbose(0) << "RESULT: The resulting spacings are: " << x0
    911               << " and " << x1 << " and " << x2 << " ." << endl;
    912           x0 = x2; // sorted in ascending order
    913         }
    914 
    915       cellvolume = 1;
    916       for (int i = 0; i < NDIM; i++)
    917         {
    918           BoxLengths.x[i] = repetition[i] * (x0 + GreatestDiameter[i]);
    919           cellvolume *= BoxLengths.x[i];
    920         }
    921 
    922       // set new box dimensions
    923       *out << Verbose(0) << "Translating to box with these boundaries." << endl;
    924       mol->CenterInBox((ofstream *) &cout, &BoxLengths);
    925     }
    926   // update Box of atoms by boundary
    927   mol->SetBoxDimension(&BoxLengths);
    928   *out << Verbose(0) << "RESULT: The resulting cell dimensions are: "
    929       << BoxLengths.x[0] << " and " << BoxLengths.x[1] << " and "
    930       << BoxLengths.x[2] << " with total volume of " << cellvolume << " "
    931       << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
     885                double ClusterVolume, double celldensity)
     886{
     887        // transform to PAS
     888        mol->PrincipalAxisSystem(out, true);
     889
     890        // some preparations beforehand
     891        bool IsAngstroem = configuration->GetIsAngstroem();
     892        Boundaries *BoundaryPoints = GetBoundaryPoints(out, mol);
     893        double clustervolume;
     894        if (ClusterVolume == 0)
     895                clustervolume = VolumeOfConvexEnvelope(out, NULL, configuration,
     896                                BoundaryPoints, mol);
     897        else
     898                clustervolume = ClusterVolume;
     899        double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol,
     900                        IsAngstroem);
     901        Vector BoxLengths;
     902        int repetition[NDIM] =
     903                { 1, 1, 1 };
     904        int TotalNoClusters = 1;
     905        for (int i = 0; i < NDIM; i++)
     906                TotalNoClusters *= repetition[i];
     907
     908        // sum up the atomic masses
     909        double totalmass = 0.;
     910        atom *Walker = mol->start;
     911        while (Walker->next != mol->end)
     912                {
     913                        Walker = Walker->next;
     914                        totalmass += Walker->type->mass;
     915                }
     916        *out << Verbose(0) << "RESULT: The summed mass is " << setprecision(10)
     917                        << totalmass << " atomicmassunit." << endl;
     918
     919        *out << Verbose(0) << "RESULT: The average density is " << setprecision(10)
     920                        << totalmass / clustervolume << " atomicmassunit/"
     921                        << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
     922
     923        // solve cubic polynomial
     924        *out << Verbose(1) << "Solving equidistant suspension in water problem ..."
     925                        << endl;
     926        double cellvolume;
     927        if (IsAngstroem)
     928                cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_A - (totalmass
     929                                / clustervolume)) / (celldensity - 1);
     930        else
     931                cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_a0 - (totalmass
     932                                / clustervolume)) / (celldensity - 1);
     933        *out << Verbose(1) << "Cellvolume needed for a density of " << celldensity
     934                        << " g/cm^3 is " << cellvolume << " " << (IsAngstroem ? "angstrom"
     935                        : "atomiclength") << "^3." << endl;
     936
     937        double minimumvolume = TotalNoClusters * (GreatestDiameter[0]
     938                        * GreatestDiameter[1] * GreatestDiameter[2]);
     939        *out << Verbose(1)
     940                        << "Minimum volume of the convex envelope contained in a rectangular box is "
     941                        << minimumvolume << " atomicmassunit/" << (IsAngstroem ? "angstrom"
     942                        : "atomiclength") << "^3." << endl;
     943        if (minimumvolume > cellvolume)
     944                {
     945                        cerr << Verbose(0)
     946                                        << "ERROR: the containing box already has a greater volume than the envisaged cell volume!"
     947                                        << endl;
     948                        cout << Verbose(0)
     949                                        << "Setting Box dimensions to minimum possible, the greatest diameters."
     950                                        << endl;
     951                        for (int i = 0; i < NDIM; i++)
     952                                BoxLengths.x[i] = GreatestDiameter[i];
     953                        mol->CenterEdge(out, &BoxLengths);
     954                }
     955        else
     956                {
     957                        BoxLengths.x[0] = (repetition[0] * GreatestDiameter[0] + repetition[1]
     958                                        * GreatestDiameter[1] + repetition[2] * GreatestDiameter[2]);
     959                        BoxLengths.x[1] = (repetition[0] * repetition[1] * GreatestDiameter[0]
     960                                        * GreatestDiameter[1] + repetition[0] * repetition[2]
     961                                        * GreatestDiameter[0] * GreatestDiameter[2] + repetition[1]
     962                                        * repetition[2] * GreatestDiameter[1] * GreatestDiameter[2]);
     963                        BoxLengths.x[2] = minimumvolume - cellvolume;
     964                        double x0 = 0., x1 = 0., x2 = 0.;
     965                        if (gsl_poly_solve_cubic(BoxLengths.x[0], BoxLengths.x[1],
     966                                        BoxLengths.x[2], &x0, &x1, &x2) == 1) // either 1 or 3 on return
     967                                *out << Verbose(0) << "RESULT: The resulting spacing is: " << x0
     968                                                << " ." << endl;
     969                        else
     970                                {
     971                                        *out << Verbose(0) << "RESULT: The resulting spacings are: " << x0
     972                                                        << " and " << x1 << " and " << x2 << " ." << endl;
     973                                        x0 = x2; // sorted in ascending order
     974                                }
     975
     976                        cellvolume = 1;
     977                        for (int i = 0; i < NDIM; i++)
     978                                {
     979                                        BoxLengths.x[i] = repetition[i] * (x0 + GreatestDiameter[i]);
     980                                        cellvolume *= BoxLengths.x[i];
     981                                }
     982
     983                        // set new box dimensions
     984                        *out << Verbose(0) << "Translating to box with these boundaries." << endl;
     985                        mol->CenterInBox((ofstream *) &cout, &BoxLengths);
     986                }
     987        // update Box of atoms by boundary
     988        mol->SetBoxDimension(&BoxLengths);
     989        *out << Verbose(0) << "RESULT: The resulting cell dimensions are: "
     990                        << BoxLengths.x[0] << " and " << BoxLengths.x[1] << " and "
     991                        << BoxLengths.x[2] << " with total volume of " << cellvolume << " "
     992                        << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
    932993}
    933994;
     
    9391000Tesselation::Tesselation()
    9401001{
    941   PointsOnBoundaryCount = 0;
    942   LinesOnBoundaryCount = 0;
    943   TrianglesOnBoundaryCount = 0;
    944   TriangleFilesWritten = 0;
     1002        PointsOnBoundaryCount = 0;
     1003        LinesOnBoundaryCount = 0;
     1004        TrianglesOnBoundaryCount = 0;
     1005        TriangleFilesWritten = 0;
    9451006}
    9461007;
     
    9511012Tesselation::~Tesselation()
    9521013{
    953   cout << Verbose(1) << "Free'ing TesselStruct ... " << endl;
    954   for (TriangleMap::iterator runner = TrianglesOnBoundary.begin(); runner
    955       != TrianglesOnBoundary.end(); runner++)
    956     {
    957       delete (runner->second);
    958     }
     1014        cout << Verbose(1) << "Free'ing TesselStruct ... " << endl;
     1015        for (TriangleMap::iterator runner = TrianglesOnBoundary.begin(); runner != TrianglesOnBoundary.end(); runner++) {
     1016                if (runner->second != NULL) {
     1017                        delete (runner->second);
     1018                        runner->second = NULL;
     1019                } else
     1020                        cerr << "ERROR: The triangle " << runner->first << " has already been free'd." << endl;
     1021        }
    9591022}
    9601023;
     
    9681031Tesselation::GuessStartingTriangle(ofstream *out)
    9691032{
    970   // 4b. create a starting triangle
    971   // 4b1. create all distances
    972   DistanceMultiMap DistanceMMap;
    973   double distance, tmp;
    974   Vector PlaneVector, TrialVector;
    975   PointMap::iterator A, B, C; // three nodes of the first triangle
    976   A = PointsOnBoundary.begin(); // the first may be chosen arbitrarily
    977 
    978   // with A chosen, take each pair B,C and sort
    979   if (A != PointsOnBoundary.end())
    980     {
    981       B = A;
    982       B++;
    983       for (; B != PointsOnBoundary.end(); B++)
    984         {
    985           C = B;
    986           C++;
    987           for (; C != PointsOnBoundary.end(); C++)
    988             {
    989               tmp = A->second->node->x.Distance(&B->second->node->x);
    990               distance = tmp * tmp;
    991               tmp = A->second->node->x.Distance(&C->second->node->x);
    992               distance += tmp * tmp;
    993               tmp = B->second->node->x.Distance(&C->second->node->x);
    994               distance += tmp * tmp;
    995               DistanceMMap.insert(DistanceMultiMapPair(distance, pair<
    996                   PointMap::iterator, PointMap::iterator> (B, C)));
    997             }
    998         }
    999     }
    1000   //    // listing distances
    1001   //    *out << Verbose(1) << "Listing DistanceMMap:";
    1002   //    for(DistanceMultiMap::iterator runner = DistanceMMap.begin(); runner != DistanceMMap.end(); runner++) {
    1003   //      *out << " " << runner->first << "(" << *runner->second.first->second << ", " << *runner->second.second->second << ")";
    1004   //    }
    1005   //    *out << endl;
    1006   // 4b2. pick three baselines forming a triangle
    1007   // 1. we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate
    1008   DistanceMultiMap::iterator baseline = DistanceMMap.begin();
    1009   for (; baseline != DistanceMMap.end(); baseline++)
    1010     {
    1011       // we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate
    1012       // 2. next, we have to check whether all points reside on only one side of the triangle
    1013       // 3. construct plane vector
    1014       PlaneVector.MakeNormalVector(&A->second->node->x,
    1015           &baseline->second.first->second->node->x,
    1016           &baseline->second.second->second->node->x);
    1017       *out << Verbose(2) << "Plane vector of candidate triangle is ";
    1018       PlaneVector.Output(out);
    1019       *out << endl;
    1020       // 4. loop over all points
    1021       double sign = 0.;
    1022       PointMap::iterator checker = PointsOnBoundary.begin();
    1023       for (; checker != PointsOnBoundary.end(); checker++)
    1024         {
    1025           // (neglecting A,B,C)
    1026           if ((checker == A) || (checker == baseline->second.first) || (checker
    1027               == baseline->second.second))
    1028             continue;
    1029           // 4a. project onto plane vector
    1030           TrialVector.CopyVector(&checker->second->node->x);
    1031           TrialVector.SubtractVector(&A->second->node->x);
    1032           distance = TrialVector.Projection(&PlaneVector);
    1033           if (fabs(distance) < 1e-4) // we need to have a small epsilon around 0 which is still ok
    1034             continue;
    1035           *out << Verbose(3) << "Projection of " << checker->second->node->Name
    1036               << " yields distance of " << distance << "." << endl;
    1037           tmp = distance / fabs(distance);
    1038           // 4b. Any have different sign to than before? (i.e. would lie outside convex hull with this starting triangle)
    1039           if ((sign != 0) && (tmp != sign))
    1040             {
    1041               // 4c. If so, break 4. loop and continue with next candidate in 1. loop
    1042               *out << Verbose(2) << "Current candidates: "
    1043                   << A->second->node->Name << ","
    1044                   << baseline->second.first->second->node->Name << ","
    1045                   << baseline->second.second->second->node->Name << " leave "
    1046                   << checker->second->node->Name << " outside the convex hull."
    1047                   << endl;
    1048               break;
    1049             }
    1050           else
    1051             { // note the sign for later
    1052               *out << Verbose(2) << "Current candidates: "
    1053                   << A->second->node->Name << ","
    1054                   << baseline->second.first->second->node->Name << ","
    1055                   << baseline->second.second->second->node->Name << " leave "
    1056                   << checker->second->node->Name << " inside the convex hull."
    1057                   << endl;
    1058               sign = tmp;
    1059             }
    1060           // 4d. Check whether the point is inside the triangle (check distance to each node
    1061           tmp = checker->second->node->x.Distance(&A->second->node->x);
    1062           int innerpoint = 0;
    1063           if ((tmp < A->second->node->x.Distance(
    1064               &baseline->second.first->second->node->x)) && (tmp
    1065               < A->second->node->x.Distance(
    1066                   &baseline->second.second->second->node->x)))
    1067             innerpoint++;
    1068           tmp = checker->second->node->x.Distance(
    1069               &baseline->second.first->second->node->x);
    1070           if ((tmp < baseline->second.first->second->node->x.Distance(
    1071               &A->second->node->x)) && (tmp
    1072               < baseline->second.first->second->node->x.Distance(
    1073                   &baseline->second.second->second->node->x)))
    1074             innerpoint++;
    1075           tmp = checker->second->node->x.Distance(
    1076               &baseline->second.second->second->node->x);
    1077           if ((tmp < baseline->second.second->second->node->x.Distance(
    1078               &baseline->second.first->second->node->x)) && (tmp
    1079               < baseline->second.second->second->node->x.Distance(
    1080                   &A->second->node->x)))
    1081             innerpoint++;
    1082           // 4e. If so, break 4. loop and continue with next candidate in 1. loop
    1083           if (innerpoint == 3)
    1084             break;
    1085         }
    1086       // 5. come this far, all on same side? Then break 1. loop and construct triangle
    1087       if (checker == PointsOnBoundary.end())
    1088         {
    1089           *out << "Looks like we have a candidate!" << endl;
    1090           break;
    1091         }
    1092     }
    1093   if (baseline != DistanceMMap.end())
    1094     {
    1095       BPS[0] = baseline->second.first->second;
    1096       BPS[1] = baseline->second.second->second;
    1097       BLS[0] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1098       BPS[0] = A->second;
    1099       BPS[1] = baseline->second.second->second;
    1100       BLS[1] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1101       BPS[0] = baseline->second.first->second;
    1102       BPS[1] = A->second;
    1103       BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1104 
    1105       // 4b3. insert created triangle
    1106       BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    1107       TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
    1108       TrianglesOnBoundaryCount++;
    1109       for (int i = 0; i < NDIM; i++)
    1110         {
    1111           LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BTS->lines[i]));
    1112           LinesOnBoundaryCount++;
    1113         }
    1114 
    1115       *out << Verbose(1) << "Starting triangle is " << *BTS << "." << endl;
    1116     }
    1117   else
    1118     {
    1119       *out << Verbose(1) << "No starting triangle found." << endl;
    1120       exit(255);
    1121     }
     1033        // 4b. create a starting triangle
     1034        // 4b1. create all distances
     1035        DistanceMultiMap DistanceMMap;
     1036        double distance, tmp;
     1037        Vector PlaneVector, TrialVector;
     1038        PointMap::iterator A, B, C; // three nodes of the first triangle
     1039        A = PointsOnBoundary.begin(); // the first may be chosen arbitrarily
     1040
     1041        // with A chosen, take each pair B,C and sort
     1042        if (A != PointsOnBoundary.end())
     1043                {
     1044                        B = A;
     1045                        B++;
     1046                        for (; B != PointsOnBoundary.end(); B++)
     1047                                {
     1048                                        C = B;
     1049                                        C++;
     1050                                        for (; C != PointsOnBoundary.end(); C++)
     1051                                                {
     1052                                                        tmp = A->second->node->x.DistanceSquared(&B->second->node->x);
     1053                                                        distance = tmp * tmp;
     1054                                                        tmp = A->second->node->x.DistanceSquared(&C->second->node->x);
     1055                                                        distance += tmp * tmp;
     1056                                                        tmp = B->second->node->x.DistanceSquared(&C->second->node->x);
     1057                                                        distance += tmp * tmp;
     1058                                                        DistanceMMap.insert(DistanceMultiMapPair(distance, pair<
     1059                                                                        PointMap::iterator, PointMap::iterator> (B, C)));
     1060                                                }
     1061                                }
     1062                }
     1063        //              // listing distances
     1064        //              *out << Verbose(1) << "Listing DistanceMMap:";
     1065        //              for(DistanceMultiMap::iterator runner = DistanceMMap.begin(); runner != DistanceMMap.end(); runner++) {
     1066        //                      *out << " " << runner->first << "(" << *runner->second.first->second << ", " << *runner->second.second->second << ")";
     1067        //              }
     1068        //              *out << endl;
     1069        // 4b2. pick three baselines forming a triangle
     1070        // 1. we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate
     1071        DistanceMultiMap::iterator baseline = DistanceMMap.begin();
     1072        for (; baseline != DistanceMMap.end(); baseline++)
     1073                {
     1074                        // we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate
     1075                        // 2. next, we have to check whether all points reside on only one side of the triangle
     1076                        // 3. construct plane vector
     1077                        PlaneVector.MakeNormalVector(&A->second->node->x,
     1078                                        &baseline->second.first->second->node->x,
     1079                                        &baseline->second.second->second->node->x);
     1080                        *out << Verbose(2) << "Plane vector of candidate triangle is ";
     1081                        PlaneVector.Output(out);
     1082                        *out << endl;
     1083                        // 4. loop over all points
     1084                        double sign = 0.;
     1085                        PointMap::iterator checker = PointsOnBoundary.begin();
     1086                        for (; checker != PointsOnBoundary.end(); checker++)
     1087                                {
     1088                                        // (neglecting A,B,C)
     1089                                        if ((checker == A) || (checker == baseline->second.first) || (checker
     1090                                                        == baseline->second.second))
     1091                                                continue;
     1092                                        // 4a. project onto plane vector
     1093                                        TrialVector.CopyVector(&checker->second->node->x);
     1094                                        TrialVector.SubtractVector(&A->second->node->x);
     1095                                        distance = TrialVector.Projection(&PlaneVector);
     1096                                        if (fabs(distance) < 1e-4) // we need to have a small epsilon around 0 which is still ok
     1097                                                continue;
     1098                                        *out << Verbose(3) << "Projection of " << checker->second->node->Name
     1099                                                        << " yields distance of " << distance << "." << endl;
     1100                                        tmp = distance / fabs(distance);
     1101                                        // 4b. Any have different sign to than before? (i.e. would lie outside convex hull with this starting triangle)
     1102                                        if ((sign != 0) && (tmp != sign))
     1103                                                {
     1104                                                        // 4c. If so, break 4. loop and continue with next candidate in 1. loop
     1105                                                        *out << Verbose(2) << "Current candidates: "
     1106                                                                        << A->second->node->Name << ","
     1107                                                                        << baseline->second.first->second->node->Name << ","
     1108                                                                        << baseline->second.second->second->node->Name << " leave "
     1109                                                                        << checker->second->node->Name << " outside the convex hull."
     1110                                                                        << endl;
     1111                                                        break;
     1112                                                }
     1113                                        else
     1114                                                { // note the sign for later
     1115                                                        *out << Verbose(2) << "Current candidates: "
     1116                                                                        << A->second->node->Name << ","
     1117                                                                        << baseline->second.first->second->node->Name << ","
     1118                                                                        << baseline->second.second->second->node->Name << " leave "
     1119                                                                        << checker->second->node->Name << " inside the convex hull."
     1120                                                                        << endl;
     1121                                                        sign = tmp;
     1122                                                }
     1123                                        // 4d. Check whether the point is inside the triangle (check distance to each node
     1124                                        tmp = checker->second->node->x.DistanceSquared(&A->second->node->x);
     1125                                        int innerpoint = 0;
     1126                                        if ((tmp < A->second->node->x.DistanceSquared(
     1127                                                        &baseline->second.first->second->node->x)) && (tmp
     1128                                                        < A->second->node->x.DistanceSquared(
     1129                                                                        &baseline->second.second->second->node->x)))
     1130                                                innerpoint++;
     1131                                        tmp = checker->second->node->x.DistanceSquared(
     1132                                                        &baseline->second.first->second->node->x);
     1133                                        if ((tmp < baseline->second.first->second->node->x.DistanceSquared(
     1134                                                        &A->second->node->x)) && (tmp
     1135                                                        < baseline->second.first->second->node->x.DistanceSquared(
     1136                                                                        &baseline->second.second->second->node->x)))
     1137                                                innerpoint++;
     1138                                        tmp = checker->second->node->x.DistanceSquared(
     1139                                                        &baseline->second.second->second->node->x);
     1140                                        if ((tmp < baseline->second.second->second->node->x.DistanceSquared(
     1141                                                        &baseline->second.first->second->node->x)) && (tmp
     1142                                                        < baseline->second.second->second->node->x.DistanceSquared(
     1143                                                                        &A->second->node->x)))
     1144                                                innerpoint++;
     1145                                        // 4e. If so, break 4. loop and continue with next candidate in 1. loop
     1146                                        if (innerpoint == 3)
     1147                                                break;
     1148                                }
     1149                        // 5. come this far, all on same side? Then break 1. loop and construct triangle
     1150                        if (checker == PointsOnBoundary.end())
     1151                                {
     1152                                        *out << "Looks like we have a candidate!" << endl;
     1153                                        break;
     1154                                }
     1155                }
     1156        if (baseline != DistanceMMap.end())
     1157                {
     1158                        BPS[0] = baseline->second.first->second;
     1159                        BPS[1] = baseline->second.second->second;
     1160                        BLS[0] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
     1161                        BPS[0] = A->second;
     1162                        BPS[1] = baseline->second.second->second;
     1163                        BLS[1] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
     1164                        BPS[0] = baseline->second.first->second;
     1165                        BPS[1] = A->second;
     1166                        BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
     1167
     1168                        // 4b3. insert created triangle
     1169                        BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     1170                        TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
     1171                        TrianglesOnBoundaryCount++;
     1172                        for (int i = 0; i < NDIM; i++)
     1173                                {
     1174                                        LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BTS->lines[i]));
     1175                                        LinesOnBoundaryCount++;
     1176                                }
     1177
     1178                        *out << Verbose(1) << "Starting triangle is " << *BTS << "." << endl;
     1179                }
     1180        else
     1181                {
     1182                        *out << Verbose(1) << "No starting triangle found." << endl;
     1183                        exit(255);
     1184                }
    11221185}
    11231186;
     
    11281191 * -# if the lines contains to only one triangle
    11291192 * -# We search all points in the boundary
    1130  *    -# if the triangle with the baseline and the current point has the smallest of angles (comparison between normal vectors
    1131  *    -# if the triangle is in forward direction of the baseline (at most 90 degrees angle between vector orthogonal to
    1132  *      baseline in triangle plane pointing out of the triangle and normal vector of new triangle)
    1133  *    -# then we have a new triangle, whose baselines we again add (or increase their TriangleCount)
     1193 *              -# if the triangle with the baseline and the current point has the smallest of angles (comparison between normal vectors
     1194 *              -# if the triangle is in forward direction of the baseline (at most 90 degrees angle between vector orthogonal to
     1195 *                      baseline in triangle plane pointing out of the triangle and normal vector of new triangle)
     1196 *              -# then we have a new triangle, whose baselines we again add (or increase their TriangleCount)
    11341197 * \param *out output stream for debugging
    11351198 * \param *configuration for IsAngstroem
     
    11381201void
    11391202Tesselation::TesselateOnBoundary(ofstream *out, config *configuration,
    1140     molecule *mol)
    1141 {
    1142   bool flag;
    1143   PointMap::iterator winner;
    1144   class BoundaryPointSet *peak = NULL;
    1145   double SmallestAngle, TempAngle;
    1146   Vector NormalVector, VirtualNormalVector, CenterVector, TempVector,
    1147       PropagationVector;
    1148   LineMap::iterator LineChecker[2];
    1149   do
    1150     {
    1151       flag = false;
    1152       for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline
    1153           != LinesOnBoundary.end(); baseline++)
    1154         if (baseline->second->TrianglesCount == 1)
    1155           {
    1156             *out << Verbose(2) << "Current baseline is between "
    1157                 << *(baseline->second) << "." << endl;
    1158             // 5a. go through each boundary point if not _both_ edges between either endpoint of the current line and this point exist (and belong to 2 triangles)
    1159             SmallestAngle = M_PI;
    1160             BTS = baseline->second->triangles.begin()->second; // there is only one triangle so far
    1161             // get peak point with respect to this base line's only triangle
    1162             for (int i = 0; i < 3; i++)
    1163               if ((BTS->endpoints[i] != baseline->second->endpoints[0])
    1164                   && (BTS->endpoints[i] != baseline->second->endpoints[1]))
    1165                 peak = BTS->endpoints[i];
    1166             *out << Verbose(3) << " and has peak " << *peak << "." << endl;
    1167             // normal vector of triangle
    1168             BTS->GetNormalVector(NormalVector);
    1169             *out << Verbose(4) << "NormalVector of base triangle is ";
    1170             NormalVector.Output(out);
    1171             *out << endl;
    1172             // offset to center of triangle
    1173             CenterVector.Zero();
    1174             for (int i = 0; i < 3; i++)
    1175               CenterVector.AddVector(&BTS->endpoints[i]->node->x);
    1176             CenterVector.Scale(1. / 3.);
    1177             *out << Verbose(4) << "CenterVector of base triangle is ";
    1178             CenterVector.Output(out);
    1179             *out << endl;
    1180             // vector in propagation direction (out of triangle)
    1181             // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection)
    1182             TempVector.CopyVector(&baseline->second->endpoints[0]->node->x);
    1183             TempVector.SubtractVector(&baseline->second->endpoints[1]->node->x);
    1184             PropagationVector.MakeNormalVector(&TempVector, &NormalVector);
    1185             TempVector.CopyVector(&CenterVector);
    1186             TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center!
    1187             //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl;
    1188             if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline
    1189               PropagationVector.Scale(-1.);
    1190             *out << Verbose(4) << "PropagationVector of base triangle is ";
    1191             PropagationVector.Output(out);
    1192             *out << endl;
    1193             winner = PointsOnBoundary.end();
    1194             for (PointMap::iterator target = PointsOnBoundary.begin(); target
    1195                 != PointsOnBoundary.end(); target++)
    1196               if ((target->second != baseline->second->endpoints[0])
    1197                   && (target->second != baseline->second->endpoints[1]))
    1198                 { // don't take the same endpoints
    1199                   *out << Verbose(3) << "Target point is " << *(target->second)
    1200                       << ":";
    1201                   bool continueflag = true;
    1202 
    1203                   VirtualNormalVector.CopyVector(
    1204                       &baseline->second->endpoints[0]->node->x);
    1205                   VirtualNormalVector.AddVector(
    1206                       &baseline->second->endpoints[0]->node->x);
    1207                   VirtualNormalVector.Scale(-1. / 2.); // points now to center of base line
    1208                   VirtualNormalVector.AddVector(&target->second->node->x); // points from center of base line to target
    1209                   TempAngle = VirtualNormalVector.Angle(&PropagationVector);
    1210                   continueflag = continueflag && (TempAngle < (M_PI/2.)); // no bends bigger than Pi/2 (90 degrees)
    1211                   if (!continueflag)
    1212                     {
    1213                       *out << Verbose(4)
    1214                           << "Angle between propagation direction and base line to "
    1215                           << *(target->second) << " is " << TempAngle
    1216                           << ", bad direction!" << endl;
    1217                       continue;
    1218                     }
    1219                   else
    1220                     *out << Verbose(4)
    1221                         << "Angle between propagation direction and base line to "
    1222                         << *(target->second) << " is " << TempAngle
    1223                         << ", good direction!" << endl;
    1224                   LineChecker[0] = baseline->second->endpoints[0]->lines.find(
    1225                       target->first);
    1226                   LineChecker[1] = baseline->second->endpoints[1]->lines.find(
    1227                       target->first);
    1228                   //            if (LineChecker[0] != baseline->second->endpoints[0]->lines.end())
    1229                   //              *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl;
    1230                   //            else
    1231                   //              *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has no line to " << *(target->second) << " as endpoint." << endl;
    1232                   //            if (LineChecker[1] != baseline->second->endpoints[1]->lines.end())
    1233                   //              *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl;
    1234                   //            else
    1235                   //              *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has no line to " << *(target->second) << " as endpoint." << endl;
    1236                   // check first endpoint (if any connecting line goes to target or at least not more than 1)
    1237                   continueflag = continueflag && (((LineChecker[0]
    1238                       == baseline->second->endpoints[0]->lines.end())
    1239                       || (LineChecker[0]->second->TrianglesCount == 1)));
    1240                   if (!continueflag)
    1241                     {
    1242                       *out << Verbose(4) << *(baseline->second->endpoints[0])
    1243                           << " has line " << *(LineChecker[0]->second)
    1244                           << " to " << *(target->second)
    1245                           << " as endpoint with "
    1246                           << LineChecker[0]->second->TrianglesCount
    1247                           << " triangles." << endl;
    1248                       continue;
    1249                     }
    1250                   // check second endpoint (if any connecting line goes to target or at least not more than 1)
    1251                   continueflag = continueflag && (((LineChecker[1]
    1252                       == baseline->second->endpoints[1]->lines.end())
    1253                       || (LineChecker[1]->second->TrianglesCount == 1)));
    1254                   if (!continueflag)
    1255                     {
    1256                       *out << Verbose(4) << *(baseline->second->endpoints[1])
    1257                           << " has line " << *(LineChecker[1]->second)
    1258                           << " to " << *(target->second)
    1259                           << " as endpoint with "
    1260                           << LineChecker[1]->second->TrianglesCount
    1261                           << " triangles." << endl;
    1262                       continue;
    1263                     }
    1264                   // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint)
    1265                   continueflag = continueflag && (!(((LineChecker[0]
    1266                       != baseline->second->endpoints[0]->lines.end())
    1267                       && (LineChecker[1]
    1268                           != baseline->second->endpoints[1]->lines.end())
    1269                       && (GetCommonEndpoint(LineChecker[0]->second,
    1270                           LineChecker[1]->second) == peak))));
    1271                   if (!continueflag)
    1272                     {
    1273                       *out << Verbose(4) << "Current target is peak!" << endl;
    1274                       continue;
    1275                     }
    1276                   // in case NOT both were found
    1277                   if (continueflag)
    1278                     { // create virtually this triangle, get its normal vector, calculate angle
    1279                       flag = true;
    1280                       VirtualNormalVector.MakeNormalVector(
    1281                           &baseline->second->endpoints[0]->node->x,
    1282                           &baseline->second->endpoints[1]->node->x,
    1283                           &target->second->node->x);
    1284                       // make it always point inward
    1285                       if (baseline->second->endpoints[0]->node->x.Projection(
    1286                           &VirtualNormalVector) > 0)
    1287                         VirtualNormalVector.Scale(-1.);
    1288                       // calculate angle
    1289                       TempAngle = NormalVector.Angle(&VirtualNormalVector);
    1290                       *out << Verbose(4) << "NormalVector is ";
    1291                       VirtualNormalVector.Output(out);
    1292                       *out << " and the angle is " << TempAngle << "." << endl;
    1293                       if (SmallestAngle > TempAngle)
    1294                         { // set to new possible winner
    1295                           SmallestAngle = TempAngle;
    1296                           winner = target;
    1297                         }
    1298                     }
    1299                 }
    1300             // 5b. The point of the above whose triangle has the greatest angle with the triangle the current line belongs to (it only belongs to one, remember!): New triangle
    1301             if (winner != PointsOnBoundary.end())
    1302               {
    1303                 *out << Verbose(2) << "Winning target point is "
    1304                     << *(winner->second) << " with angle " << SmallestAngle
    1305                     << "." << endl;
    1306                 // create the lins of not yet present
    1307                 BLS[0] = baseline->second;
    1308                 // 5c. add lines to the line set if those were new (not yet part of a triangle), delete lines that belong to two triangles)
    1309                 LineChecker[0] = baseline->second->endpoints[0]->lines.find(
    1310                     winner->first);
    1311                 LineChecker[1] = baseline->second->endpoints[1]->lines.find(
    1312                     winner->first);
    1313                 if (LineChecker[0]
    1314                     == baseline->second->endpoints[0]->lines.end())
    1315                   { // create
    1316                     BPS[0] = baseline->second->endpoints[0];
    1317                     BPS[1] = winner->second;
    1318                     BLS[1] = new class BoundaryLineSet(BPS,
    1319                         LinesOnBoundaryCount);
    1320                     LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount,
    1321                         BLS[1]));
    1322                     LinesOnBoundaryCount++;
    1323                   }
    1324                 else
    1325                   BLS[1] = LineChecker[0]->second;
    1326                 if (LineChecker[1]
    1327                     == baseline->second->endpoints[1]->lines.end())
    1328                   { // create
    1329                     BPS[0] = baseline->second->endpoints[1];
    1330                     BPS[1] = winner->second;
    1331                     BLS[2] = new class BoundaryLineSet(BPS,
    1332                         LinesOnBoundaryCount);
    1333                     LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount,
    1334                         BLS[2]));
    1335                     LinesOnBoundaryCount++;
    1336                   }
    1337                 else
    1338                   BLS[2] = LineChecker[1]->second;
    1339                 BTS = new class BoundaryTriangleSet(BLS,
    1340                     TrianglesOnBoundaryCount);
    1341                 TrianglesOnBoundary.insert(TrianglePair(
    1342                     TrianglesOnBoundaryCount, BTS));
    1343                 TrianglesOnBoundaryCount++;
    1344               }
    1345             else
    1346               {
    1347                 *out << Verbose(1)
    1348                     << "I could not determine a winner for this baseline "
    1349                     << *(baseline->second) << "." << endl;
    1350               }
    1351 
    1352             // 5d. If the set of lines is not yet empty, go to 5. and continue
    1353           }
    1354         else
    1355           *out << Verbose(2) << "Baseline candidate " << *(baseline->second)
    1356               << " has a triangle count of "
    1357               << baseline->second->TrianglesCount << "." << endl;
    1358     }
    1359   while (flag);
     1203                molecule *mol)
     1204{
     1205        bool flag;
     1206        PointMap::iterator winner;
     1207        class BoundaryPointSet *peak = NULL;
     1208        double SmallestAngle, TempAngle;
     1209        Vector NormalVector, VirtualNormalVector, CenterVector, TempVector,
     1210                        PropagationVector;
     1211        LineMap::iterator LineChecker[2];
     1212        do
     1213                {
     1214                        flag = false;
     1215                        for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline
     1216                                        != LinesOnBoundary.end(); baseline++)
     1217                                if (baseline->second->TrianglesCount == 1)
     1218                                        {
     1219                                                *out << Verbose(2) << "Current baseline is between "
     1220                                                                << *(baseline->second) << "." << endl;
     1221                                                // 5a. go through each boundary point if not _both_ edges between either endpoint of the current line and this point exist (and belong to 2 triangles)
     1222                                                SmallestAngle = M_PI;
     1223                                                BTS = baseline->second->triangles.begin()->second; // there is only one triangle so far
     1224                                                // get peak point with respect to this base line's only triangle
     1225                                                for (int i = 0; i < 3; i++)
     1226                                                        if ((BTS->endpoints[i] != baseline->second->endpoints[0])
     1227                                                                        && (BTS->endpoints[i] != baseline->second->endpoints[1]))
     1228                                                                peak = BTS->endpoints[i];
     1229                                                *out << Verbose(3) << " and has peak " << *peak << "." << endl;
     1230                                                // normal vector of triangle
     1231                                                BTS->GetNormalVector(NormalVector);
     1232                                                *out << Verbose(4) << "NormalVector of base triangle is ";
     1233                                                NormalVector.Output(out);
     1234                                                *out << endl;
     1235                                                // offset to center of triangle
     1236                                                CenterVector.Zero();
     1237                                                for (int i = 0; i < 3; i++)
     1238                                                        CenterVector.AddVector(&BTS->endpoints[i]->node->x);
     1239                                                CenterVector.Scale(1. / 3.);
     1240                                                *out << Verbose(4) << "CenterVector of base triangle is ";
     1241                                                CenterVector.Output(out);
     1242                                                *out << endl;
     1243                                                // vector in propagation direction (out of triangle)
     1244                                                // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection)
     1245                                                TempVector.CopyVector(&baseline->second->endpoints[0]->node->x);
     1246                                                TempVector.SubtractVector(&baseline->second->endpoints[1]->node->x);
     1247                                                PropagationVector.MakeNormalVector(&TempVector, &NormalVector);
     1248                                                TempVector.CopyVector(&CenterVector);
     1249                                                TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center!
     1250                                                //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl;
     1251                                                if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline
     1252                                                        PropagationVector.Scale(-1.);
     1253                                                *out << Verbose(4) << "PropagationVector of base triangle is ";
     1254                                                PropagationVector.Output(out);
     1255                                                *out << endl;
     1256                                                winner = PointsOnBoundary.end();
     1257                                                for (PointMap::iterator target = PointsOnBoundary.begin(); target
     1258                                                                != PointsOnBoundary.end(); target++)
     1259                                                        if ((target->second != baseline->second->endpoints[0])
     1260                                                                        && (target->second != baseline->second->endpoints[1]))
     1261                                                                { // don't take the same endpoints
     1262                                                                        *out << Verbose(3) << "Target point is " << *(target->second)
     1263                                                                                        << ":";
     1264                                                                        bool continueflag = true;
     1265
     1266                                                                        VirtualNormalVector.CopyVector(
     1267                                                                                        &baseline->second->endpoints[0]->node->x);
     1268                                                                        VirtualNormalVector.AddVector(
     1269                                                                                        &baseline->second->endpoints[0]->node->x);
     1270                                                                        VirtualNormalVector.Scale(-1. / 2.); // points now to center of base line
     1271                                                                        VirtualNormalVector.AddVector(&target->second->node->x); // points from center of base line to target
     1272                                                                        TempAngle = VirtualNormalVector.Angle(&PropagationVector);
     1273                                                                        continueflag = continueflag && (TempAngle < (M_PI/2.)); // no bends bigger than Pi/2 (90 degrees)
     1274                                                                        if (!continueflag)
     1275                                                                                {
     1276                                                                                        *out << Verbose(4)
     1277                                                                                                        << "Angle between propagation direction and base line to "
     1278                                                                                                        << *(target->second) << " is " << TempAngle
     1279                                                                                                        << ", bad direction!" << endl;
     1280                                                                                        continue;
     1281                                                                                }
     1282                                                                        else
     1283                                                                                *out << Verbose(4)
     1284                                                                                                << "Angle between propagation direction and base line to "
     1285                                                                                                << *(target->second) << " is " << TempAngle
     1286                                                                                                << ", good direction!" << endl;
     1287                                                                        LineChecker[0] = baseline->second->endpoints[0]->lines.find(
     1288                                                                                        target->first);
     1289                                                                        LineChecker[1] = baseline->second->endpoints[1]->lines.find(
     1290                                                                                        target->first);
     1291                                                                        //                                              if (LineChecker[0] != baseline->second->endpoints[0]->lines.end())
     1292                                                                        //                                                      *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl;
     1293                                                                        //                                              else
     1294                                                                        //                                                      *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has no line to " << *(target->second) << " as endpoint." << endl;
     1295                                                                        //                                              if (LineChecker[1] != baseline->second->endpoints[1]->lines.end())
     1296                                                                        //                                                      *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl;
     1297                                                                        //                                              else
     1298                                                                        //                                                      *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has no line to " << *(target->second) << " as endpoint." << endl;
     1299                                                                        // check first endpoint (if any connecting line goes to target or at least not more than 1)
     1300                                                                        continueflag = continueflag && (((LineChecker[0]
     1301                                                                                        == baseline->second->endpoints[0]->lines.end())
     1302                                                                                        || (LineChecker[0]->second->TrianglesCount == 1)));
     1303                                                                        if (!continueflag)
     1304                                                                                {
     1305                                                                                        *out << Verbose(4) << *(baseline->second->endpoints[0])
     1306                                                                                                        << " has line " << *(LineChecker[0]->second)
     1307                                                                                                        << " to " << *(target->second)
     1308                                                                                                        << " as endpoint with "
     1309                                                                                                        << LineChecker[0]->second->TrianglesCount
     1310                                                                                                        << " triangles." << endl;
     1311                                                                                        continue;
     1312                                                                                }
     1313                                                                        // check second endpoint (if any connecting line goes to target or at least not more than 1)
     1314                                                                        continueflag = continueflag && (((LineChecker[1]
     1315                                                                                        == baseline->second->endpoints[1]->lines.end())
     1316                                                                                        || (LineChecker[1]->second->TrianglesCount == 1)));
     1317                                                                        if (!continueflag)
     1318                                                                                {
     1319                                                                                        *out << Verbose(4) << *(baseline->second->endpoints[1])
     1320                                                                                                        << " has line " << *(LineChecker[1]->second)
     1321                                                                                                        << " to " << *(target->second)
     1322                                                                                                        << " as endpoint with "
     1323                                                                                                        << LineChecker[1]->second->TrianglesCount
     1324                                                                                                        << " triangles." << endl;
     1325                                                                                        continue;
     1326                                                                                }
     1327                                                                        // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint)
     1328                                                                        continueflag = continueflag && (!(((LineChecker[0]
     1329                                                                                        != baseline->second->endpoints[0]->lines.end())
     1330                                                                                        && (LineChecker[1]
     1331                                                                                                        != baseline->second->endpoints[1]->lines.end())
     1332                                                                                        && (GetCommonEndpoint(LineChecker[0]->second,
     1333                                                                                                        LineChecker[1]->second) == peak))));
     1334                                                                        if (!continueflag)
     1335                                                                                {
     1336                                                                                        *out << Verbose(4) << "Current target is peak!" << endl;
     1337                                                                                        continue;
     1338                                                                                }
     1339                                                                        // in case NOT both were found
     1340                                                                        if (continueflag)
     1341                                                                                { // create virtually this triangle, get its normal vector, calculate angle
     1342                                                                                        flag = true;
     1343                                                                                        VirtualNormalVector.MakeNormalVector(
     1344                                                                                                        &baseline->second->endpoints[0]->node->x,
     1345                                                                                                        &baseline->second->endpoints[1]->node->x,
     1346                                                                                                        &target->second->node->x);
     1347                                                                                        // make it always point inward
     1348                                                                                        if (baseline->second->endpoints[0]->node->x.Projection(
     1349                                                                                                        &VirtualNormalVector) > 0)
     1350                                                                                                VirtualNormalVector.Scale(-1.);
     1351                                                                                        // calculate angle
     1352                                                                                        TempAngle = NormalVector.Angle(&VirtualNormalVector);
     1353                                                                                        *out << Verbose(4) << "NormalVector is ";
     1354                                                                                        VirtualNormalVector.Output(out);
     1355                                                                                        *out << " and the angle is " << TempAngle << "." << endl;
     1356                                                                                        if (SmallestAngle > TempAngle)
     1357                                                                                                { // set to new possible winner
     1358                                                                                                        SmallestAngle = TempAngle;
     1359                                                                                                        winner = target;
     1360                                                                                                }
     1361                                                                                }
     1362                                                                }
     1363                                                // 5b. The point of the above whose triangle has the greatest angle with the triangle the current line belongs to (it only belongs to one, remember!): New triangle
     1364                                                if (winner != PointsOnBoundary.end())
     1365                                                        {
     1366                                                                *out << Verbose(2) << "Winning target point is "
     1367                                                                                << *(winner->second) << " with angle " << SmallestAngle
     1368                                                                                << "." << endl;
     1369                                                                // create the lins of not yet present
     1370                                                                BLS[0] = baseline->second;
     1371                                                                // 5c. add lines to the line set if those were new (not yet part of a triangle), delete lines that belong to two triangles)
     1372                                                                LineChecker[0] = baseline->second->endpoints[0]->lines.find(
     1373                                                                                winner->first);
     1374                                                                LineChecker[1] = baseline->second->endpoints[1]->lines.find(
     1375                                                                                winner->first);
     1376                                                                if (LineChecker[0]
     1377                                                                                == baseline->second->endpoints[0]->lines.end())
     1378                                                                        { // create
     1379                                                                                BPS[0] = baseline->second->endpoints[0];
     1380                                                                                BPS[1] = winner->second;
     1381                                                                                BLS[1] = new class BoundaryLineSet(BPS,
     1382                                                                                                LinesOnBoundaryCount);
     1383                                                                                LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount,
     1384                                                                                                BLS[1]));
     1385                                                                                LinesOnBoundaryCount++;
     1386                                                                        }
     1387                                                                else
     1388                                                                        BLS[1] = LineChecker[0]->second;
     1389                                                                if (LineChecker[1]
     1390                                                                                == baseline->second->endpoints[1]->lines.end())
     1391                                                                        { // create
     1392                                                                                BPS[0] = baseline->second->endpoints[1];
     1393                                                                                BPS[1] = winner->second;
     1394                                                                                BLS[2] = new class BoundaryLineSet(BPS,
     1395                                                                                                LinesOnBoundaryCount);
     1396                                                                                LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount,
     1397                                                                                                BLS[2]));
     1398                                                                                LinesOnBoundaryCount++;
     1399                                                                        }
     1400                                                                else
     1401                                                                        BLS[2] = LineChecker[1]->second;
     1402                                                                BTS = new class BoundaryTriangleSet(BLS,
     1403                                                                                TrianglesOnBoundaryCount);
     1404                                                                TrianglesOnBoundary.insert(TrianglePair(
     1405                                                                                TrianglesOnBoundaryCount, BTS));
     1406                                                                TrianglesOnBoundaryCount++;
     1407                                                        }
     1408                                                else
     1409                                                        {
     1410                                                                *out << Verbose(1)
     1411                                                                                << "I could not determine a winner for this baseline "
     1412                                                                                << *(baseline->second) << "." << endl;
     1413                                                        }
     1414
     1415                                                // 5d. If the set of lines is not yet empty, go to 5. and continue
     1416                                        }
     1417                                else
     1418                                        *out << Verbose(2) << "Baseline candidate " << *(baseline->second)
     1419                                                        << " has a triangle count of "
     1420                                                        << baseline->second->TrianglesCount << "." << endl;
     1421                }
     1422        while (flag);
    13601423
    13611424}
     
    13681431Tesselation::AddPoint(atom *Walker)
    13691432{
    1370   PointTestPair InsertUnique;
    1371   BPS[0] = new class BoundaryPointSet(Walker);
    1372   InsertUnique = PointsOnBoundary.insert(PointPair(Walker->nr, BPS[0]));
    1373   if (InsertUnique.second) // if new point was not present before, increase counter
    1374     PointsOnBoundaryCount++;
     1433        PointTestPair InsertUnique;
     1434        BPS[0] = new class BoundaryPointSet(Walker);
     1435        InsertUnique = PointsOnBoundary.insert(PointPair(Walker->nr, BPS[0]));
     1436        if (InsertUnique.second) // if new point was not present before, increase counter
     1437                PointsOnBoundaryCount++;
    13751438}
    13761439;
     
    13841447Tesselation::AddTrianglePoint(atom* Candidate, int n)
    13851448{
    1386   PointTestPair InsertUnique;
    1387   TPS[n] = new class BoundaryPointSet(Candidate);
    1388   InsertUnique = PointsOnBoundary.insert(PointPair(Candidate->nr, TPS[n]));
    1389   if (InsertUnique.second) // if new point was not present before, increase counter
    1390     {
    1391       PointsOnBoundaryCount++;
    1392     }
    1393   else
    1394     {
    1395       delete TPS[n];
    1396       cout << Verbose(2) << "Atom " << *((InsertUnique.first)->second->node)
    1397           << " gibt's schon in der PointMap." << endl;
    1398       TPS[n] = (InsertUnique.first)->second;
    1399     }
     1449        PointTestPair InsertUnique;
     1450        TPS[n] = new class BoundaryPointSet(Candidate);
     1451        InsertUnique = PointsOnBoundary.insert(PointPair(Candidate->nr, TPS[n]));
     1452        if (InsertUnique.second) // if new point was not present before, increase counter
     1453                {
     1454                        PointsOnBoundaryCount++;
     1455                }
     1456        else
     1457                {
     1458                        delete TPS[n];
     1459                        cout << Verbose(2) << "Atom " << *((InsertUnique.first)->second->node)
     1460                                        << " gibt's schon in der PointMap." << endl;
     1461                        TPS[n] = (InsertUnique.first)->second;
     1462                }
    14001463}
    14011464;
     
    14101473void
    14111474Tesselation::AddTriangleLine(class BoundaryPointSet *a,
    1412     class BoundaryPointSet *b, int n)
    1413 {
    1414   LineMap::iterator LineWalker;
    1415   //cout << "Manually checking endpoints for line." << endl;
    1416   if ((a->lines.find(b->node->nr))->first == b->node->nr)
    1417   //If a line is there, how do I recognize that beyond a shadow of a doubt?
    1418     {
    1419       //cout << Verbose(2) << "Line exists already, retrieving it from LinesOnBoundarySet" << endl;
    1420 
    1421       LineWalker = LinesOnBoundary.end();
    1422       LineWalker--;
    1423 
    1424       while (LineWalker->second->endpoints[0]->node->nr != min(a->node->nr,
    1425           b->node->nr) or LineWalker->second->endpoints[1]->node->nr != max(
    1426           a->node->nr, b->node->nr))
    1427         {
    1428           //cout << Verbose(1) << "Looking for line which already exists"<< endl;
    1429           LineWalker--;
    1430         }
    1431       BPS[0] = LineWalker->second->endpoints[0];
    1432       BPS[1] = LineWalker->second->endpoints[1];
    1433       BLS[n] = LineWalker->second;
    1434 
    1435     }
    1436   else
    1437     {
    1438       cout << Verbose(2)
    1439           << "Adding line which has not been used before between "
    1440           << *(a->node) << " and " << *(b->node) << "." << endl;
    1441       BPS[0] = a;
    1442       BPS[1] = b;
    1443       BLS[n] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1444 
    1445       LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BLS[n]));
    1446       LinesOnBoundaryCount++;
    1447 
    1448     }
     1475                class BoundaryPointSet *b, int n)
     1476{
     1477        LineMap::iterator LineWalker;
     1478        //cout << "Manually checking endpoints for line." << endl;
     1479        if ((a->lines.find(b->node->nr)) != a->lines.end()) // ->first == b->node->nr)
     1480        //If a line is there, how do I recognize that beyond a shadow of a doubt?
     1481                {
     1482                        //cout << Verbose(2) << "Line exists already, retrieving it from LinesOnBoundarySet" << endl;
     1483
     1484                        LineWalker = LinesOnBoundary.end();
     1485                        LineWalker--;
     1486
     1487                        while (LineWalker->second->endpoints[0]->node->nr != min(a->node->nr,
     1488                                        b->node->nr) or LineWalker->second->endpoints[1]->node->nr != max(
     1489                                        a->node->nr, b->node->nr))
     1490                                {
     1491                                        //cout << Verbose(1) << "Looking for line which already exists"<< endl;
     1492                                        LineWalker--;
     1493                                }
     1494                        BPS[0] = LineWalker->second->endpoints[0];
     1495                        BPS[1] = LineWalker->second->endpoints[1];
     1496                        BLS[n] = LineWalker->second;
     1497
     1498                }
     1499        else
     1500                {
     1501                        cout << Verbose(2)
     1502                                        << "Adding line which has not been used before between "
     1503                                        << *(a->node) << " and " << *(b->node) << "." << endl;
     1504                        BPS[0] = a;
     1505                        BPS[1] = b;
     1506                        BLS[n] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
     1507
     1508                        LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BLS[n]));
     1509                        LinesOnBoundaryCount++;
     1510
     1511                }
    14491512}
    14501513;
     
    14571520{
    14581521
    1459   cout << Verbose(1) << "Adding triangle to its lines" << endl;
    1460   int i = 0;
    1461   TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
    1462   TrianglesOnBoundaryCount++;
    1463 
    1464   /*
    1465    * this is apparently done when constructing triangle
    1466 
    1467    for (i=0; i<3; i++)
    1468    {
    1469    BLS[i]->AddTriangle(BTS);
    1470    }
    1471    */
    1472 }
    1473 ;
     1522        cout << Verbose(1) << "Adding triangle to its lines" << endl;
     1523        int i = 0;
     1524        TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
     1525        TrianglesOnBoundaryCount++;
     1526
     1527        /*
     1528         * this is apparently done when constructing triangle
     1529
     1530         for (i=0; i<3; i++)
     1531         {
     1532         BLS[i]->AddTriangle(BTS);
     1533         }
     1534         */
     1535}
     1536;
     1537
     1538
     1539double det_get(gsl_matrix *A, int inPlace) {
     1540        /*
     1541        inPlace = 1 => A is replaced with the LU decomposed copy.
     1542        inPlace = 0 => A is retained, and a copy is used for LU.
     1543        */
     1544
     1545        double det;
     1546        int signum;
     1547        gsl_permutation *p = gsl_permutation_alloc(A->size1);
     1548        gsl_matrix *tmpA;
     1549
     1550        if (inPlace)
     1551        tmpA = A;
     1552        else {
     1553        gsl_matrix *tmpA = gsl_matrix_alloc(A->size1, A->size2);
     1554        gsl_matrix_memcpy(tmpA , A);
     1555        }
     1556
     1557
     1558        gsl_linalg_LU_decomp(tmpA , p , &signum);
     1559        det = gsl_linalg_LU_det(tmpA , signum);
     1560        gsl_permutation_free(p);
     1561        if (! inPlace)
     1562        gsl_matrix_free(tmpA);
     1563
     1564        return det;
     1565};
     1566
     1567void get_sphere(Vector *center, Vector &a, Vector &b, Vector &c, double RADIUS)
     1568{
     1569        gsl_matrix *A = gsl_matrix_calloc(3,3);
     1570        double m11, m12, m13, m14;
     1571
     1572        for(int i=0;i<3;i++) {
     1573                gsl_matrix_set(A, i, 0, a.x[i]);
     1574                gsl_matrix_set(A, i, 1, b.x[i]);
     1575                gsl_matrix_set(A, i, 2, c.x[i]);
     1576        }
     1577        m11 = det_get(A, 1);
     1578
     1579        for(int i=0;i<3;i++) {
     1580                gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
     1581                gsl_matrix_set(A, i, 1, b.x[i]);
     1582                gsl_matrix_set(A, i, 2, c.x[i]);
     1583        }
     1584        m12 = det_get(A, 1);
     1585
     1586        for(int i=0;i<3;i++) {
     1587                gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
     1588                gsl_matrix_set(A, i, 1, a.x[i]);
     1589                gsl_matrix_set(A, i, 2, c.x[i]);
     1590        }
     1591        m13 = det_get(A, 1);
     1592
     1593        for(int i=0;i<3;i++) {
     1594                gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
     1595                gsl_matrix_set(A, i, 1, a.x[i]);
     1596                gsl_matrix_set(A, i, 2, b.x[i]);
     1597        }
     1598        m14 = det_get(A, 1);
     1599
     1600        if (fabs(m11) < MYEPSILON)
     1601                cerr << "ERROR: three points are colinear." << endl;
     1602
     1603        center->x[0] =  0.5 * m12/ m11;
     1604        center->x[1] = -0.5 * m13/ m11;
     1605        center->x[2] =  0.5 * m14/ m11;
     1606
     1607        if (fabs(a.Distance(center) - RADIUS) > MYEPSILON)
     1608                cerr << "ERROR: The given center is further way by " << fabs(a.Distance(center) - RADIUS) << " from a than RADIUS." << endl;
     1609
     1610        gsl_matrix_free(A);
     1611};
     1612
     1613
    14741614
    14751615/**
     
    14891629 * @param Umkreisradius double radius of circumscribing circle
    14901630 */
    1491 
    1492   void Get_center_of_sphere(Vector* Center, Vector a, Vector b, Vector c, Vector* Direction, Vector* AlternativeDirection,
    1493       double HalfplaneIndicator, double AlternativeIndicator, double alpha, double beta, double gamma, double RADIUS, double Umkreisradius)
    1494   {
    1495     Vector TempNormal, helper;
    1496     double Restradius;
    1497 
    1498     *Center = a * sin(2.*alpha) + b * sin(2.*beta) + c * sin(2.*gamma) ;
    1499     Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));
    1500     // Here we calculated center of circumscribing circle, using barycentric coordinates
    1501 
    1502     TempNormal.CopyVector(&a);
    1503     TempNormal.SubtractVector(&b);
    1504     helper.CopyVector(&a);
    1505     helper.SubtractVector(&c);
    1506     TempNormal.VectorProduct(&helper);
    1507     if (fabs(HalfplaneIndicator) < MYEPSILON)
    1508       {
    1509         if ((TempNormal.ScalarProduct(AlternativeDirection) <0 and AlternativeIndicator >0) or (TempNormal.ScalarProduct(AlternativeDirection) >0 and AlternativeIndicator <0))
    1510           {
    1511             TempNormal.Scale(-1);
    1512           }
    1513       }
    1514     else
    1515       {
    1516         if (TempNormal.ScalarProduct(Direction)<0 && HalfplaneIndicator >0 || TempNormal.ScalarProduct(Direction)>0 && HalfplaneIndicator<0)
    1517           {
    1518             TempNormal.Scale(-1);
    1519           }
    1520       }
    1521 
    1522     TempNormal.Normalize();
    1523     Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius);
    1524     TempNormal.Scale(Restradius);
    1525 
    1526     Center->AddVector(&TempNormal);
    1527   }
    1528   ;
    1529 
     1631void Get_center_of_sphere(Vector* Center, Vector a, Vector b, Vector c, Vector *NewUmkreismittelpunkt, Vector* Direction, Vector* AlternativeDirection,
     1632                double HalfplaneIndicator, double AlternativeIndicator, double alpha, double beta, double gamma, double RADIUS, double Umkreisradius)
     1633{
     1634        Vector TempNormal, helper;
     1635        double Restradius;
     1636        Vector OtherCenter;
     1637        cout << Verbose(3) << "Begin of Get_center_of_sphere.\n";
     1638        Center->Zero();
     1639        helper.CopyVector(&a);
     1640        helper.Scale(sin(2.*alpha));
     1641        Center->AddVector(&helper);
     1642        helper.CopyVector(&b);
     1643        helper.Scale(sin(2.*beta));
     1644        Center->AddVector(&helper);
     1645        helper.CopyVector(&c);
     1646        helper.Scale(sin(2.*gamma));
     1647        Center->AddVector(&helper);
     1648        //*Center = a * sin(2.*alpha) + b * sin(2.*beta) + c * sin(2.*gamma) ;
     1649        Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));
     1650        NewUmkreismittelpunkt->CopyVector(Center);
     1651        cout << Verbose(4) << "Center of new circumference is " << *NewUmkreismittelpunkt << ".\n";
     1652        // Here we calculated center of circumscribing circle, using barycentric coordinates
     1653        cout << Verbose(4) << "Center of circumference is " << *Center << " in direction " << *Direction << ".\n";
     1654
     1655        TempNormal.CopyVector(&a);
     1656        TempNormal.SubtractVector(&b);
     1657        helper.CopyVector(&a);
     1658        helper.SubtractVector(&c);
     1659        TempNormal.VectorProduct(&helper);
     1660        if (fabs(HalfplaneIndicator) < MYEPSILON)
     1661                {
     1662                        if ((TempNormal.ScalarProduct(AlternativeDirection) <0 and AlternativeIndicator >0) or (TempNormal.ScalarProduct(AlternativeDirection) >0 and AlternativeIndicator <0))
     1663                                {
     1664                                        TempNormal.Scale(-1);
     1665                                }
     1666                }
     1667        else
     1668                {
     1669                        if (TempNormal.ScalarProduct(Direction)<0 && HalfplaneIndicator >0 || TempNormal.ScalarProduct(Direction)>0 && HalfplaneIndicator<0)
     1670                                {
     1671                                        TempNormal.Scale(-1);
     1672                                }
     1673                }
     1674
     1675        TempNormal.Normalize();
     1676        Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius);
     1677        cout << Verbose(4) << "Height of center of circumference to center of sphere is " << Restradius << ".\n";
     1678        TempNormal.Scale(Restradius);
     1679        cout << Verbose(4) << "Shift vector to sphere of circumference is " << TempNormal << ".\n";
     1680
     1681        Center->AddVector(&TempNormal);
     1682        cout << Verbose(0) << "Center of sphere of circumference is " << *Center << ".\n";
     1683        get_sphere(&OtherCenter, a, b, c, RADIUS);
     1684        cout << Verbose(0) << "OtherCenter of sphere of circumference is " << OtherCenter << ".\n";
     1685        cout << Verbose(3) << "End of Get_center_of_sphere.\n";
     1686};
    15301687
    15311688/** This recursive function finds a third point, to form a triangle with two given ones.
    15321689 * Two atoms are fixed, a candidate is supplied, additionally two vectors for direction distinction, a Storage area to \
    1533  *  supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \
    1534  *  upon which we operate.
    1535  *  If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \
    1536  *  direction and angle into Storage.
    1537  *  We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \
    1538  *  with all neighbours of the candidate.
     1690 *      supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \
     1691 *      upon which we operate.
     1692 *      If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \
     1693 *      direction and angle into Storage.
     1694 *      We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \
     1695 *      with all neighbours of the candidate.
    15391696 * @param a first point
    15401697 * @param b second point
     
    15521709 * @param mol molecule structure with atoms and bonds
    15531710 */
    1554 
    1555 void Find_next_suitable_point_via_Angle_of_Sphere(atom* a, atom* b, atom* c, atom* Candidate, atom* Parent,
    1556     int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint,
    1557     atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol)
    1558 {
    1559   //cout << "ReferencePoint is " << ReferencePoint.x[0] << " "<< ReferencePoint.x[1] << " "<< ReferencePoint.x[2] << " "<< endl;
    1560   /* OldNormal is normal vector on the old triangle
    1561    * direction1 is normal on the triangle line, from which we come, as well as on OldNormal.
    1562    * Chord points from b to a!!!
    1563    */
    1564   Vector dif_a; //Vector from a to candidate
    1565   Vector dif_b; //Vector from b to candidate
    1566   Vector AngleCheck;
    1567   Vector TempNormal, Umkreismittelpunkt;
    1568   Vector Mittelpunkt;
    1569 
    1570   double CurrentEpsilon = 0.1;
    1571   double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius, Restradius, Distance;
    1572   double BallAngle, AlternativeSign;
    1573   atom *Walker; // variable atom point
    1574 
    1575 
    1576   dif_a.CopyVector(&(a->x));
    1577   dif_a.SubtractVector(&(Candidate->x));
    1578   dif_b.CopyVector(&(b->x));
    1579   dif_b.SubtractVector(&(Candidate->x));
    1580   AngleCheck.CopyVector(&(Candidate->x));
    1581   AngleCheck.SubtractVector(&(a->x));
    1582   AngleCheck.ProjectOntoPlane(Chord);
    1583 
    1584   SideA = dif_b.Norm();
    1585   SideB = dif_a.Norm();
    1586   SideC = Chord->Norm();
    1587   //Chord->Scale(-1);
    1588 
    1589   alpha = Chord->Angle(&dif_a);
    1590   beta = M_PI - Chord->Angle(&dif_b);
    1591   gamma = dif_a.Angle(&dif_b);
    1592 
    1593 
    1594   if (a != Candidate and b != Candidate and c != Candidate)
    1595     {
    1596 
    1597       Umkreisradius = SideA / 2.0 / sin(alpha);
    1598       //cout << Umkreisradius << endl;
    1599       //cout << SideB / 2.0 / sin(beta) << endl;
    1600       //cout << SideC / 2.0 / sin(gamma) << endl;
    1601 
    1602       if (Umkreisradius < RADIUS) //Checking whether ball will at least rest on points.
    1603         {
    1604           cout << Verbose(1) << "Candidate is "<< *Candidate << endl;
    1605           sign = AngleCheck.ScalarProduct(direction1);
    1606           if (fabs(sign)<MYEPSILON)
    1607             {
    1608               if (AngleCheck.ScalarProduct(OldNormal)<0)
    1609                 {
    1610                   sign =0;
    1611                   AlternativeSign=1;
    1612                 }
    1613               else
    1614                 {
    1615                   sign =0;
    1616                   AlternativeSign=-1;
    1617                 }
    1618             }
    1619           else
    1620             {
    1621               sign /= fabs(sign);
    1622             }
    1623 
    1624 
    1625 
    1626           Get_center_of_sphere(&Mittelpunkt, (a->x), (b->x), (Candidate->x), OldNormal, direction1, sign, AlternativeSign, alpha, beta, gamma, RADIUS, Umkreisradius);
    1627 
    1628           AngleCheck.CopyVector(&ReferencePoint);
    1629           AngleCheck.Scale(-1);
    1630           //cout << "AngleCheck is " << AngleCheck.x[0] << " "<< AngleCheck.x[1] << " "<< AngleCheck.x[2] << " "<< endl;
    1631           AngleCheck.AddVector(&Mittelpunkt);
    1632           //cout << "AngleCheck is " << AngleCheck.x[0] << " "<< AngleCheck.x[1] << " "<< AngleCheck.x[2] << " "<< endl;
    1633 
    1634           BallAngle = AngleCheck.Angle(OldNormal);
    1635 
    1636           //cout << "direction1 is " << direction1->x[0] <<" "<< direction1->x[1] <<" "<< direction1->x[2] <<" " << endl;
    1637           //cout << "AngleCheck is " << AngleCheck.x[0] << " "<< AngleCheck.x[1] << " "<< AngleCheck.x[2] << " "<< endl;
    1638 
    1639           cout << Verbose(1) << "BallAngle is " << BallAngle << " Sign is " << sign << endl;
    1640 
    1641           if (AngleCheck.ScalarProduct(direction1) >=0)
    1642             {
    1643               if (Storage[0]< -1.5) // first Candidate at all
    1644                 {
    1645 
    1646                   cout << "Next better candidate is " << *Candidate << " with ";
    1647                   Opt_Candidate = Candidate;
    1648                   Storage[0] = sign;
    1649                   Storage[1] = AlternativeSign;
    1650                   Storage[2] = BallAngle;
    1651                   cout << "Angle is " << Storage[2] << ", Halbraum ist "
    1652                     << Storage[0] << endl;
    1653 
    1654 
    1655                 }
    1656               else
    1657                 {
    1658                   if ( Storage[2] > BallAngle)
    1659                     {
    1660                       cout << "Next better candidate is " << *Candidate << " with ";
    1661                       Opt_Candidate = Candidate;
    1662                       Storage[0] = sign;
    1663                       Storage[1] = AlternativeSign;
    1664                       Storage[2] = BallAngle;
    1665                       cout << "Angle is " << Storage[2] << ", Halbraum ist "
    1666                         << Storage[0] << endl;
    1667                     }
    1668                   else
    1669                     {
    1670                       //if (DEBUG)
    1671                         cout << "Looses to better candidate" << endl;
    1672 
    1673                     }
    1674                 }
    1675               }
    1676             else
    1677               {
    1678                 //if (DEBUG)
    1679                   cout << "Refused due to bad direction of ball centre." << endl;
    1680               }
    1681           }
    1682         else
    1683           {
    1684             //if (DEBUG)
    1685               cout << "Doesn't satisfy requirements for circumscribing circle" << endl;
    1686           }
    1687       }
    1688     else
    1689       {
    1690         //if (DEBUG)
    1691           cout << "identisch mit Ursprungslinie" << endl;
    1692 
    1693       }
    1694 
    1695 
    1696 
    1697   if (RecursionLevel < 9) // Seven is the recursion level threshold.
    1698     {
    1699       for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) // go through all bond
    1700         {
    1701           Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(
    1702               Candidate);
    1703           if (Walker == Parent)
    1704             { // don't go back the same bond
    1705               continue;
    1706             }
    1707           else
    1708             {
    1709               Find_next_suitable_point_via_Angle_of_Sphere(a, b, c, Walker, Candidate, RecursionLevel
    1710                   + 1, Chord, direction1, OldNormal, ReferencePoint, Opt_Candidate, Storage, RADIUS,
    1711                   mol); //call function again
    1712             }
    1713         }
    1714     }
    1715 }
    1716 ;
    1717 
    1718 
    1719   /** This recursive function finds a third point, to form a triangle with two given ones.
    1720    * Two atoms are fixed, a candidate is supplied, additionally two vectors for direction distinction, a Storage area to \
    1721    *  supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \
    1722    *  upon which we operate.
    1723    *  If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \
    1724    *  direction and angle into Storage.
    1725    *  We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \
    1726    *  with all neighbours of the candidate.
    1727    * @param a first point
    1728    * @param b second point
    1729    * @param Candidate base point along whose bonds to start looking from
    1730    * @param Parent point to avoid during search as its wrong direction
    1731    * @param RecursionLevel contains current recursion depth
    1732    * @param Chord baseline vector of first and second point
    1733    * @param d1 second in plane vector (along with \a Chord) of the triangle the baseline belongs to
    1734    * @param OldNormal normal of the triangle which the baseline belongs to
    1735    * @param Opt_Candidate candidate reference to return
    1736    * @param Opt_Mittelpunkt Centerpoint of ball, when resting on Opt_Candidate
    1737    * @param Storage array containing two angles of current Opt_Candidate
    1738    * @param RADIUS radius of ball
    1739    * @param mol molecule structure with atoms and bonds
    1740    */
    1741 
    1742 void Find_next_suitable_point(atom* a, atom* b, atom* Candidate, atom* Parent,
    1743     int RecursionLevel, Vector *Chord, Vector *d1, Vector *OldNormal,
    1744     atom*& Opt_Candidate, Vector *Opt_Mittelpunkt, double *Storage, const double RADIUS, molecule* mol)
    1745 {
    1746   /* OldNormal is normal vector on the old triangle
    1747    * d1 is normal on the triangle line, from which we come, as well as on OldNormal.
    1748    * Chord points from b to a!!!
    1749    */
    1750   Vector dif_a; //Vector from a to candidate
    1751   Vector dif_b; //Vector from b to candidate
    1752   Vector AngleCheck, AngleCheckReference, DirectionCheckPoint;
    1753   Vector TempNormal, Umkreismittelpunkt, Mittelpunkt;
    1754 
    1755   double CurrentEpsilon = 0.1;
    1756   double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius, Restradius, Distance;
    1757   double BallAngle;
    1758   atom *Walker; // variable atom point
    1759 
    1760 
    1761   dif_a.CopyVector(&(a->x));
    1762   dif_a.SubtractVector(&(Candidate->x));
    1763   dif_b.CopyVector(&(b->x));
    1764   dif_b.SubtractVector(&(Candidate->x));
    1765   DirectionCheckPoint.CopyVector(&dif_a);
    1766   DirectionCheckPoint.Scale(-1);
    1767   DirectionCheckPoint.ProjectOntoPlane(Chord);
    1768 
    1769   SideA = dif_b.Norm();
    1770   SideB = dif_a.Norm();
    1771   SideC = Chord->Norm();
    1772   //Chord->Scale(-1);
    1773 
    1774   alpha = Chord->Angle(&dif_a);
    1775   beta = M_PI - Chord->Angle(&dif_b);
    1776   gamma = dif_a.Angle(&dif_b);
    1777 
    1778 
    1779   if (DEBUG)
    1780     {
    1781       cout << "Atom number" << Candidate->nr << endl;
    1782       Candidate->x.Output((ofstream *) &cout);
    1783       cout << "number of bonds " << mol->NumberOfBondsPerAtom[Candidate->nr]
    1784           << endl;
    1785     }
    1786 
    1787   if (a != Candidate and b != Candidate)
    1788     {
    1789       //      alpha = dif_a.Angle(&dif_b) / 2.;
    1790       //      SideA = Chord->Norm() / 2.;// (Chord->Norm()/2.) / sin(0.5*alpha);
    1791       //      SideB = dif_a.Norm();
    1792       //      centerline = SideA * SideA + SideB * SideB - 2. * SideA * SideB * cos(
    1793       //          alpha); // note this is squared of center line length
    1794       //      centerline = (Chord->Norm()/2.) / sin(0.5*alpha);
    1795       // Those are remains from Freddie. Needed?
    1796 
    1797 
    1798 
    1799       Umkreisradius = SideA / 2.0 / sin(alpha);
    1800       //cout << Umkreisradius << endl;
    1801       //cout << SideB / 2.0 / sin(beta) << endl;
    1802       //cout << SideC / 2.0 / sin(gamma) << endl;
    1803 
    1804       if (Umkreisradius < RADIUS && DirectionCheckPoint.ScalarProduct(&(Candidate->x))>0) //Checking whether ball will at least rest o points.
    1805         {
    1806 
    1807           // intermediate calculations to aquire centre of sphere, called Mittelpunkt:
    1808 
    1809           Umkreismittelpunkt = (a->x) * sin(2.*alpha) + b->x * sin(2.*beta) + (Candidate->x) * sin(2.*gamma) ;
    1810           Umkreismittelpunkt.Scale(1/(sin(2*alpha) + sin(2*beta) + sin(2*gamma)));
    1811 
    1812           TempNormal.CopyVector(&dif_a);
    1813           TempNormal.VectorProduct(&dif_b);
    1814           if (TempNormal.ScalarProduct(OldNormal)<0 && sign>0 || TempNormal.ScalarProduct(OldNormal)>0 && sign<0)
    1815             {
    1816               TempNormal.Scale(-1);
    1817             }
    1818           TempNormal.Normalize();
    1819           Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius);
    1820           TempNormal.Scale(Restradius);
    1821 
    1822           Mittelpunkt.CopyVector(&Umkreismittelpunkt);
    1823           Mittelpunkt.AddVector(&TempNormal);  //this is center of sphere supported by a, b and Candidate
    1824 
    1825           AngleCheck.CopyVector(Chord);
    1826           AngleCheck.Scale(-0.5);
    1827           AngleCheck.SubtractVector(&(b->x));
    1828           AngleCheckReference.CopyVector(&AngleCheck);
    1829           AngleCheckReference.AddVector(Opt_Mittelpunkt);
    1830           AngleCheck.AddVector(&Mittelpunkt);
    1831 
    1832           BallAngle = AngleCheck.Angle(&AngleCheckReference);
    1833 
    1834           d1->ProjectOntoPlane(&AngleCheckReference);
    1835           sign = AngleCheck.ScalarProduct(d1);
    1836           sign /= fabs(sign); // +1 if in direction of triangle plane, -1 if in other direction...
    1837 
    1838 
    1839           if (Storage[0]< -1.5) // first Candidate at all
    1840             {
    1841 
    1842               cout << "Next better candidate is " << *Candidate << " with ";
    1843               Opt_Candidate = Candidate;
    1844               Storage[0] = sign;
    1845               Storage[1] = BallAngle;
    1846               Opt_Mittelpunkt->CopyVector(&Mittelpunkt);
    1847               cout << "Angle is " << Storage[1] << ", Halbraum ist "
    1848                   << Storage[0] << endl;
    1849 
    1850 
    1851             }
    1852           else
    1853             {
    1854               /*
    1855                * removed due to change in criterium, now checking angle of ball to old normal.
    1856               //We will now check for non interference, that is if the new candidate would have the Opt_Candidate
    1857               //within the ball.
    1858 
    1859               Distance = Opt_Candidate->x.Distance(&Mittelpunkt);
    1860               //cout << "Opt_Candidate " << Opt_Candidate << " has distance " << Distance << " to Center of Candidate " << endl;
    1861 
    1862 
    1863               if (Distance >RADIUS) // We have no interference and may now check whether the new point is better.
    1864                 */
    1865                 {
    1866                   //cout << "Atom " << Candidate << " has distance " << Candidate->x.Distance(Opt_Mittelpunkt) << " to Center of Candidate " << endl;
    1867 
    1868                   if (((Storage[0] < 0 && fabs(sign - Storage[0]) > CurrentEpsilon)))  //This will give absolute preference to those in "right-hand" quadrants
    1869                       //(Candidate->x.Distance(Opt_Mittelpunkt) < RADIUS))    //and those where Candidate would be within old Sphere.
    1870                     {
    1871                       cout << "Next better candidate is " << *Candidate << " with ";
    1872                       Opt_Candidate = Candidate;
    1873                       Storage[0] = sign;
    1874                       Storage[1] = BallAngle;
    1875                       Opt_Mittelpunkt->CopyVector(&Mittelpunkt);
    1876                       cout << "Angle is " << Storage[1] << ", Halbraum ist "
    1877                           << Storage[0] << endl;
    1878 
    1879 
    1880                     }
    1881                   else
    1882                     {
    1883                       if ((fabs(sign - Storage[0]) < CurrentEpsilon && sign > 0
    1884                           && Storage[1] > BallAngle) ||
    1885                           (fabs(sign - Storage[0]) < CurrentEpsilon && sign < 0
    1886                           && Storage[1] < BallAngle))
    1887                       //Depending on quadrant we prefer higher or lower atom with respect to Triangle normal first.
    1888                         {
    1889                           cout << "Next better candidate is " << *Candidate << " with ";
    1890                           Opt_Candidate = Candidate;
    1891                           Storage[0] = sign;
    1892                           Storage[1] = BallAngle;
    1893                           Opt_Mittelpunkt->CopyVector(&Mittelpunkt);
    1894                           cout << "Angle is " << Storage[1] << ", Halbraum ist "
    1895                               << Storage[0] << endl;
    1896                         }
    1897 
    1898                     }
    1899                 }
    1900               /*
    1901                * This is for checking point-angle and presence of Candidates in Ball, currently we are checking the ball Angle.
    1902                *
    1903                 else
    1904                 {
    1905                   if (sign>0 && BallAngle>0 && Storage[0]<0)
    1906                     {
    1907                       cout << "Next better candidate is " << *Candidate << " with ";
    1908                       Opt_Candidate = Candidate;
    1909                       Storage[0] = sign;
    1910                       Storage[1] = BallAngle;
    1911                       Opt_Mittelpunkt->CopyVector(&Mittelpunkt);
    1912                       cout << "Angle is " << Storage[1] << ", Halbraum ist "
    1913                       << Storage[0] << endl;
    1914 
    1915 //Debugging purposes only
    1916                       cout << "Umkreismittelpunkt has coordinates" << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] <<" "<<Umkreismittelpunkt.x[2] << endl;
    1917                       cout << "Candidate has coordinates" << Candidate->x.x[0]<< " " << Candidate->x.x[1] << " " << Candidate->x.x[2] << endl;
    1918                       cout << "a has coordinates" << a->x.x[0]<< " " << a->x.x[1] << " " << a->x.x[2] << endl;
    1919                       cout << "b has coordinates" << b->x.x[0]<< " " << b->x.x[1] << " " << b->x.x[2] << endl;
    1920                       cout << "Mittelpunkt has coordinates" << Mittelpunkt.x[0] << " " << Mittelpunkt.x[1]<< " "  <<Mittelpunkt.x[2] << endl;
    1921                       cout << "Umkreisradius ist " << Umkreisradius << endl;
    1922                       cout << "Restradius ist " << Restradius << endl;
    1923                       cout << "TempNormal has coordinates " << TempNormal.x[0] << " " << TempNormal.x[1] << " " << TempNormal.x[2] << " " << endl;
    1924                       cout << "OldNormal has coordinates " << OldNormal->x[0] << " " << OldNormal->x[1] << " " << OldNormal->x[2] << " " << endl;
    1925                       cout << "Dist a to UmkreisMittelpunkt " << a->x.Distance(&Umkreismittelpunkt) << endl;
    1926                       cout << "Dist b to UmkreisMittelpunkt " << b->x.Distance(&Umkreismittelpunkt) << endl;
    1927                       cout << "Dist Candidate to UmkreisMittelpunkt " << Candidate->x.Distance(&Umkreismittelpunkt) << endl;
    1928                       cout << "Dist a to Mittelpunkt " << a->x.Distance(&Mittelpunkt) << endl;
    1929                       cout << "Dist b to Mittelpunkt " << b->x.Distance(&Mittelpunkt) << endl;
    1930                       cout << "Dist Candidate to Mittelpunkt " << Candidate->x.Distance(&Mittelpunkt) << endl;
    1931 
    1932 
    1933 
    1934                     }
    1935                   else
    1936                     {
    1937                       if (DEBUG)
    1938                         cout << "Looses to better candidate" << endl;
    1939                     }
    1940                 }
    1941                 */
    1942             }
    1943         }
    1944       else
    1945         {
    1946           if (DEBUG)
    1947             {
    1948               cout << "Doesn't satisfy requirements for circumscribing circle" << endl;
    1949             }
    1950         }
    1951     }
    1952 
    1953   else
    1954     {
    1955       if (DEBUG)
    1956         cout << "identisch mit Ursprungslinie" << endl;
    1957     }
    1958 
    1959   if (RecursionLevel < 9) // Five is the recursion level threshold.
    1960     {
    1961       for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) // go through all bond
    1962         {
    1963           Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(
    1964               Candidate);
    1965           if (Walker == Parent)
    1966             { // don't go back the same bond
    1967               continue;
    1968             }
    1969           else
    1970             {
    1971               Find_next_suitable_point(a, b, Walker, Candidate, RecursionLevel
    1972                   + 1, Chord, d1, OldNormal, Opt_Candidate, Opt_Mittelpunkt, Storage, RADIUS,
    1973                   mol); //call function again
    1974 
    1975             }
    1976         }
    1977     }
    1978 }
    1979 ;
     1711void Tesselation::Find_next_suitable_point_via_Angle_of_Sphere(atom* a, atom* b, atom* c, atom* Candidate, atom* Parent,
     1712                int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint,
     1713                atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol)
     1714{
     1715        cout << Verbose(2) << "Begin of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n";
     1716        cout << Verbose(3) << "Candidate is "<< *Candidate << endl;
     1717        cout << Verbose(4) << "Baseline vector is " << *Chord << "." << endl;
     1718        cout << Verbose(4) << "ReferencePoint is " << ReferencePoint << "." << endl;
     1719        cout << Verbose(4) << "Normal of base triangle is " << *OldNormal << "." << endl;
     1720        cout << Verbose(4) << "Search direction is " << *direction1 << "." << endl;
     1721        /* OldNormal is normal vector on the old triangle
     1722         * direction1 is normal on the triangle line, from which we come, as well as on OldNormal.
     1723         * Chord points from b to a!!!
     1724         */
     1725        Vector dif_a; //Vector from a to candidate
     1726        Vector dif_b; //Vector from b to candidate
     1727        Vector AngleCheck;
     1728        Vector TempNormal, Umkreismittelpunkt;
     1729        Vector Mittelpunkt;
     1730
     1731        double CurrentEpsilon = 0.1;
     1732        double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius, Restradius, Distance;
     1733        double BallAngle, AlternativeSign;
     1734        atom *Walker; // variable atom point
     1735
     1736        Vector NewUmkreismittelpunkt;
     1737
     1738        if (a != Candidate and b != Candidate and c != Candidate) {
     1739                cout << Verbose(3) << "We have a unique candidate!" << endl;
     1740                dif_a.CopyVector(&(a->x));
     1741                dif_a.SubtractVector(&(Candidate->x));
     1742                dif_b.CopyVector(&(b->x));
     1743                dif_b.SubtractVector(&(Candidate->x));
     1744                AngleCheck.CopyVector(&(Candidate->x));
     1745                AngleCheck.SubtractVector(&(a->x));
     1746                AngleCheck.ProjectOntoPlane(Chord);
     1747
     1748                SideA = dif_b.Norm();
     1749                SideB = dif_a.Norm();
     1750                SideC = Chord->Norm();
     1751                //Chord->Scale(-1);
     1752
     1753                alpha = Chord->Angle(&dif_a);
     1754                beta = M_PI - Chord->Angle(&dif_b);
     1755                gamma = dif_a.Angle(&dif_b);
     1756
     1757                cout << Verbose(2) << "Base triangle has sides " << dif_a << ", " << dif_b << ", " << *Chord << " with angles " << alpha/M_PI*180. << ", " << beta/M_PI*180. << ", " << gamma/M_PI*180. << "." << endl;
     1758
     1759                if (fabs(M_PI - alpha - beta - gamma) > MYEPSILON) {
     1760                        cerr << Verbose(0) << "WARNING: sum of angles for base triangle " << (alpha + beta + gamma)/M_PI*180. << " != 180.\n";
     1761                        cout << Verbose(1) << "Base triangle has sides " << dif_a << ", " << dif_b << ", " << *Chord << " with angles " << alpha/M_PI*180. << ", " << beta/M_PI*180. << ", " << gamma/M_PI*180. << "." << endl;
     1762                }
     1763
     1764                if ((M_PI*179./180. > alpha) && (M_PI*179./180. > beta) && (M_PI*179./180. > gamma)) {
     1765                        Umkreisradius = SideA / 2.0 / sin(alpha);
     1766                        //cout << Umkreisradius << endl;
     1767                        //cout << SideB / 2.0 / sin(beta) << endl;
     1768                        //cout << SideC / 2.0 / sin(gamma) << endl;
     1769
     1770                        if (Umkreisradius < RADIUS) { //Checking whether ball will at least rest on points.
     1771                                cout << Verbose(3) << "Circle of circumference would fit: " << Umkreisradius << " < " << RADIUS << "." << endl;
     1772                                cout << Verbose(2) << "Candidate is "<< *Candidate << endl;
     1773                                sign = AngleCheck.ScalarProduct(direction1);
     1774                                if (fabs(sign)<MYEPSILON) {
     1775                                        if (AngleCheck.ScalarProduct(OldNormal)<0) {
     1776                                                sign =0;
     1777                                                AlternativeSign=1;
     1778                                        } else {
     1779                                                sign =0;
     1780                                                AlternativeSign=-1;
     1781                                        }
     1782                                } else {
     1783                                        sign /= fabs(sign);
     1784                                }
     1785                                if (sign >= 0) {
     1786                                        cout << Verbose(3) << "Candidate is in search direction: " << sign << "." << endl;
     1787                                        Get_center_of_sphere(&Mittelpunkt, (a->x), (b->x), (Candidate->x), &NewUmkreismittelpunkt, OldNormal, direction1, sign, AlternativeSign, alpha, beta, gamma, RADIUS, Umkreisradius);
     1788                                        Mittelpunkt.SubtractVector(&ReferencePoint);
     1789                                        cout << Verbose(3) << "Reference vector to sphere's center is " << Mittelpunkt << "." << endl;
     1790                                        BallAngle = Mittelpunkt.Angle(OldNormal);
     1791                                        cout << Verbose(3) << "Angle between normal of base triangle and center of ball sphere is :" << BallAngle << "." << endl;
     1792
     1793                                        //cout << "direction1 is " << *direction1 << "." << endl;
     1794                                        //cout << "Mittelpunkt is " << Mittelpunkt << "."<< endl;
     1795                                        //cout << Verbose(3) << "BallAngle is " << BallAngle << " Sign is " << sign << endl;
     1796
     1797                                        NewUmkreismittelpunkt.SubtractVector(&ReferencePoint);
     1798
     1799                                        if ((Mittelpunkt.ScalarProduct(direction1) >=0) || (fabs(NewUmkreismittelpunkt.Norm()) < MYEPSILON)) {
     1800                                                if (Storage[0]< -1.5) { // first Candidate at all
     1801                                                        if (1) {//if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) {
     1802                                                                cout << Verbose(2) << "First good candidate is " << *Candidate << " with ";
     1803                                                                Opt_Candidate = Candidate;
     1804                                                                Storage[0] = sign;
     1805                                                                Storage[1] = AlternativeSign;
     1806                                                                Storage[2] = BallAngle;
     1807                                                                cout << " angle " << Storage[2] << " and Up/Down " << Storage[0] << endl;
     1808                                                        } else
     1809                                                                cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl;
     1810                                                } else {
     1811                                                        if ( Storage[2] > BallAngle) {
     1812                                                                if (1) { //if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) {
     1813                                                                        cout << Verbose(2) << "Next better candidate is " << *Candidate << " with ";
     1814                                                                        Opt_Candidate = Candidate;
     1815                                                                        Storage[0] = sign;
     1816                                                                        Storage[1] = AlternativeSign;
     1817                                                                        Storage[2] = BallAngle;
     1818                                                                        cout << " angle " << Storage[2] << " and Up/Down " << Storage[0] << endl;
     1819                                                                } else
     1820                                                                        cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl;
     1821                                                        } else {
     1822                                                                if (DEBUG) {
     1823                                                                        cout << Verbose(3) << *Candidate << " looses against better candidate " << *Opt_Candidate << "." << endl;
     1824                                                                }
     1825                                                        }
     1826                                                }
     1827                                        } else {
     1828                                                if (DEBUG) {
     1829                                                        cout << Verbose(3) << *Candidate << " refused due to Up/Down sign which is " << sign << endl;
     1830                                                }
     1831                                        }
     1832                                } else {
     1833                                        if (DEBUG) {
     1834                                                cout << Verbose(3) << *Candidate << " is not in search direction." << endl;
     1835                                        }
     1836                                }
     1837                        } else {
     1838                                if (DEBUG) {
     1839                                        cout << Verbose(3) << *Candidate << " would have circumference of " << Umkreisradius << " bigger than ball's radius " << RADIUS << "." << endl;
     1840                                }
     1841                        }
     1842                } else {
     1843                        if (DEBUG) {
     1844                                cout << Verbose(0) << "Triangle consisting of " << *Candidate << ", " << *a << " and " << *b << " has an angle >150!" << endl;
     1845                        }
     1846                }
     1847        } else {
     1848                if (DEBUG) {
     1849                        cout << Verbose(3) << *Candidate << " is either " << *a << " or " << *b << "." << endl;
     1850                }
     1851        }
     1852
     1853        if (RecursionLevel < 5) { // Seven is the recursion level threshold.
     1854                for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) { // go through all bond
     1855                        Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate);
     1856                        if (Walker == Parent) { // don't go back the same bond
     1857                                continue;
     1858                        } else {
     1859                                Find_next_suitable_point_via_Angle_of_Sphere(a, b, c, Walker, Candidate, RecursionLevel+1, Chord, direction1, OldNormal, ReferencePoint, Opt_Candidate, Storage, RADIUS, mol); //call function again
     1860                        }
     1861                }
     1862        }
     1863        cout << Verbose(2) << "End of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n";
     1864}
     1865;
     1866
     1867
     1868/** Constructs the center of the circumcircle defined by three points \a *a, \a *b and \a *c.
     1869 * \param *Center new center on return
     1870 * \param *a first point
     1871 * \param *b second point
     1872 * \param *c third point
     1873 */
     1874void GetCenterofCircumcircle(Vector *Center, Vector *a, Vector *b, Vector *c)
     1875{
     1876        Vector helper;
     1877        double alpha, beta, gamma;
     1878        Vector SideA, SideB, SideC;
     1879        SideA.CopyVector(b);
     1880        SideA.SubtractVector(c);
     1881        SideB.CopyVector(c);
     1882        SideB.SubtractVector(a);
     1883        SideC.CopyVector(a);
     1884        SideC.SubtractVector(b);
     1885        alpha = M_PI - SideB.Angle(&SideC);
     1886        beta = M_PI - SideC.Angle(&SideA);
     1887        gamma = M_PI - SideA.Angle(&SideB);
     1888        cout << Verbose(3) << "INFO: alpha = " << alpha/M_PI*180. << ", beta = " << beta/M_PI*180. << ", gamma = " << gamma/M_PI*180. << "." << endl;
     1889        if (fabs(M_PI - alpha - beta - gamma) > HULLEPSILON)
     1890                cerr << "Sum of angles " << (alpha+beta+gamma)/M_PI*180. << " > 180 degrees by " << fabs(M_PI - alpha - beta - gamma)/M_PI*180. << "!" << endl;
     1891
     1892        Center->Zero();
     1893        helper.CopyVector(a);
     1894        helper.Scale(sin(2.*alpha));
     1895        Center->AddVector(&helper);
     1896        helper.CopyVector(b);
     1897        helper.Scale(sin(2.*beta));
     1898        Center->AddVector(&helper);
     1899        helper.CopyVector(c);
     1900        helper.Scale(sin(2.*gamma));
     1901        Center->AddVector(&helper);
     1902        Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));
     1903};
     1904
     1905/** Returns the parameter "path length" for a given \a NewSphereCenter relative to \a OldSphereCenter on a circle on the plane \a CirclePlaneNormal with center \a CircleCenter and radius \a CircleRadius.
     1906 * Test whether the \a NewSphereCenter is really on the given plane and in distance \a CircleRadius from \a CircleCenter.
     1907 * It calculates the angle, making it unique on [0,2.*M_PI) by comparing to SearchDirection.
     1908 * Also the new center is invalid if it the same as the old one and does not lie right above (\a NormalVector) the base line (\a CircleCenter).
     1909 * \param CircleCenter Center of the parameter circle
     1910 * \param CirclePlaneNormal normal vector to plane of the parameter circle
     1911 * \param CircleRadius radius of the parameter circle
     1912 * \param NewSphereCenter new center of a circumcircle
     1913 * \param OldSphereCenter old center of a circumcircle, defining the zero "path length" on the parameter circle
     1914 * \param NormalVector normal vector
     1915 * \param SearchDirection search direction to make angle unique on return.
     1916 * \return Angle between \a NewSphereCenter and \a OldSphereCenter relative to \a CircleCenter, 2.*M_PI if one test fails
     1917 */
     1918double GetPathLengthonCircumCircle(Vector &CircleCenter, Vector &CirclePlaneNormal, double CircleRadius, Vector &NewSphereCenter, Vector &OldSphereCenter, Vector &NormalVector, Vector &SearchDirection)
     1919{
     1920        Vector helper;
     1921        double radius, alpha;
     1922
     1923        helper.CopyVector(&NewSphereCenter);
     1924        // test whether new center is on the parameter circle's plane
     1925        if (fabs(helper.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
     1926                cerr << "ERROR: Something's very wrong here: NewSphereCenter is not on the band's plane as desired by " <<fabs(helper.ScalarProduct(&CirclePlaneNormal))        << "!" << endl;
     1927                helper.ProjectOntoPlane(&CirclePlaneNormal);
     1928        }
     1929        radius = helper.ScalarProduct(&helper);
     1930        // test whether the new center vector has length of CircleRadius
     1931        if (fabs(radius - CircleRadius) > HULLEPSILON)
     1932                cerr << Verbose(1) << "ERROR: The projected center of the new sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
     1933        alpha = helper.Angle(&OldSphereCenter);
     1934        // make the angle unique by checking the halfplanes/search direction
     1935        if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)      // acos is not unique on [0, 2.*M_PI), hence extra check to decide between two half intervals
     1936                alpha = 2.*M_PI - alpha;
     1937        cout << Verbose(2) << "INFO: RelativeNewSphereCenter is " << helper << ", RelativeOldSphereCenter is " << OldSphereCenter << " and resulting angle is " << alpha << "." << endl;
     1938        radius = helper.Distance(&OldSphereCenter);
     1939        helper.ProjectOntoPlane(&NormalVector);
     1940        // check whether new center is somewhat away or at least right over the current baseline to prevent intersecting triangles
     1941        if ((radius > HULLEPSILON) || (helper.Norm() < HULLEPSILON)) {
     1942                cout << Verbose(2) << "INFO: Distance between old and new center is " << radius << " and between new center and baseline center is " << helper.Norm() << "." << endl;
     1943                return alpha;
     1944        } else {
     1945                cout << Verbose(1) << "ERROR: NewSphereCenter " << helper << " is too close to OldSphereCenter" << OldSphereCenter << "." << endl;
     1946                return 2.*M_PI;
     1947        }
     1948};
     1949
     1950
     1951/** This recursive function finds a third point, to form a triangle with two given ones.
     1952 * The idea is as follows: A sphere with fixed radius is (almost) uniquely defined in space by three points
     1953 * that sit on its boundary. Hence, when two points are given and we look for the (next) third point, then
     1954 * the center of the sphere is still fixed up to a single parameter. The band of possible values
     1955 * describes a circle in 3D-space. The old center of the sphere for the current base triangle gives
     1956 * us the "null" on this circle, the new center of the candidate point will be some way along this
     1957 * circle. The shorter the way the better is the candidate. Note that the direction is clearly given
     1958 * by the normal vector of the base triangle that always points outwards by construction.
     1959 * Hence, we construct a Center of this circle which sits right in the middle of the current base line.
     1960 * We construct the normal vector that defines the plane this circle lies in, it is just in the
     1961 * direction of the baseline. And finally, we need the radius of the circle, which is given by the rest
     1962 * with respect to the length of the baseline and the sphere's fixed \a RADIUS.
     1963 * Note that there is one difficulty: The circumcircle is uniquely defined, but for the circumsphere's center
     1964 * there are two possibilities which becomes clear from the construction as seen below. Hence, we must check
     1965 * both.
     1966 * Note also that the acos() function is not unique on [0, 2.*M_PI). Hence, we need an additional check
     1967 * to decide for one of the two possible angles. Therefore we need a SearchDirection and to make this check
     1968 * sensible we need OldSphereCenter to be orthogonal to it. Either we construct SearchDirection orthogonal
     1969 * right away, or -- what we do here -- we rotate the relative sphere centers such that this orthogonality
     1970 * holds. Then, the normalized projection onto the SearchDirection is either +1 or -1 and thus states whether
     1971 * the angle is uniquely in either (0,M_PI] or [M_PI, 2.*M_PI).
     1972 * @param BaseTriangle BoundaryTriangleSet of the current base triangle with all three points
     1973 * @param BaseLine BoundaryLineSet of BaseTriangle with the current base line
     1974 * @param OptCandidate candidate reference on return
     1975 * @param OptCandidateCenter candidate's sphere center on return
     1976 * @param ShortestAngle the current path length on this circle band for the current Opt_Candidate
     1977 * @param RADIUS radius of sphere
     1978 * @param *LC LinkedCell structure with neighbouring atoms
     1979 */
     1980// void Find_next_suitable_point(class BoundaryTriangleSet *BaseTriangle, class BoundaryLineSet *BaseLine, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC)
     1981// {
     1982//       atom *Walker = NULL;
     1983//       Vector CircleCenter;   // center of the circle, i.e. of the band of sphere's centers
     1984//       Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in
     1985//       Vector OldSphereCenter;         // center of the sphere defined by the three points of BaseTriangle
     1986//       Vector NewSphereCenter;         // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility
     1987//       Vector OtherNewSphereCenter;    // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility
     1988//       Vector NewNormalVector;         // normal vector of the Candidate's triangle
     1989//       Vector SearchDirection;         // vector that points out of BaseTriangle and is orthonormal to its NormalVector (i.e. the desired direction for the best Candidate)
     1990//       Vector helper;
     1991//       LinkedAtoms *List = NULL;
     1992//       double CircleRadius; // radius of this circle
     1993//       double radius;
     1994//       double alpha, Otheralpha; // angles (i.e. parameter for the circle).
     1995//       double Nullalpha; // angle between OldSphereCenter and NormalVector of base triangle
     1996//       int N[NDIM], Nlower[NDIM], Nupper[NDIM];
     1997//       atom *Candidate = NULL;
     1998//
     1999//       cout << Verbose(1) << "Begin of Find_next_suitable_point" << endl;
     2000//
     2001//       cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << BaseTriangle->NormalVector << "." << endl;
     2002//
     2003//       // construct center of circle
     2004//       CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x));
     2005//       CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x);
     2006//       CircleCenter.Scale(0.5);
     2007//
     2008//       // construct normal vector of circle
     2009//       CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x);
     2010//       CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x);
     2011//
     2012//       // calculate squared radius of circle
     2013//       radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
     2014//       if (radius/4. < RADIUS*RADIUS) {
     2015//               CircleRadius = RADIUS*RADIUS - radius/4.;
     2016//               CirclePlaneNormal.Normalize();
     2017//               cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
     2018//
     2019//               // construct old center
     2020//               GetCenterofCircumcircle(&OldSphereCenter, &(BaseTriangle->endpoints[0]->node->x), &(BaseTriangle->endpoints[1]->node->x), &(BaseTriangle->endpoints[2]->node->x));
     2021//               helper.CopyVector(&BaseTriangle->NormalVector);        // normal vector ensures that this is correct center of the two possible ones
     2022//               radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&OldSphereCenter);
     2023//               helper.Scale(sqrt(RADIUS*RADIUS - radius));
     2024//               OldSphereCenter.AddVector(&helper);
     2025//               OldSphereCenter.SubtractVector(&CircleCenter);
     2026//               cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;
     2027//
     2028//               // test whether old center is on the band's plane
     2029//               if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
     2030//                       cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl;
     2031//                       OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal);
     2032//               }
     2033//               radius = OldSphereCenter.ScalarProduct(&OldSphereCenter);
     2034//               if (fabs(radius - CircleRadius) < HULLEPSILON) {
     2035//
     2036//                       // construct SearchDirection
     2037//                       SearchDirection.MakeNormalVector(&BaseTriangle->NormalVector, &CirclePlaneNormal);
     2038//                       helper.CopyVector(&BaseLine->endpoints[0]->node->x);
     2039//                       for(int i=0;i<3;i++)   // just take next different endpoint
     2040//                               if ((BaseTriangle->endpoints[i]->node != BaseLine->endpoints[0]->node) && (BaseTriangle->endpoints[i]->node != BaseLine->endpoints[1]->node)) {
     2041//                                       helper.SubtractVector(&BaseTriangle->endpoints[i]->node->x);
     2042//                               }
     2043//                       if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)     // ohoh, SearchDirection points inwards!
     2044//                               SearchDirection.Scale(-1.);
     2045//                       SearchDirection.ProjectOntoPlane(&OldSphereCenter);
     2046//                       SearchDirection.Normalize();
     2047//                       cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
     2048//                       if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {     // rotated the wrong way!
     2049//                               cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl;
     2050//                       }
     2051//
     2052//                       if (LC->SetIndexToVector(&CircleCenter)) {     // get cell for the starting atom
     2053//                               for(int i=0;i<NDIM;i++) // store indices of this cell
     2054//                                       N[i] = LC->n[i];
     2055//                               cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
     2056//                       } else {
     2057//                               cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl;
     2058//                               return;
     2059//                       }
     2060//                       // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
     2061//                       cout << Verbose(2) << "LC Intervals:";
     2062//                       for (int i=0;i<NDIM;i++) {
     2063//                               Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
     2064//                               Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
     2065//                               cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
     2066//                       }
     2067//                       cout << endl;
     2068//                       for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
     2069//                               for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
     2070//                                       for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
     2071//                                               List = LC->GetCurrentCell();
     2072//                                               cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
     2073//                                               if (List != NULL) {
     2074//                                                       for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
     2075//                                                               Candidate = (*Runner);
     2076//
     2077//                                                               // check for three unique points
     2078//                                                               if ((Candidate != BaseTriangle->endpoints[0]->node) && (Candidate != BaseTriangle->endpoints[1]->node) && (Candidate != BaseTriangle->endpoints[2]->node)) {
     2079//                                                                       cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl;
     2080//
     2081//                                                                       // construct both new centers
     2082//                                                                       GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x));
     2083//                                                                       OtherNewSphereCenter.CopyVector(&NewSphereCenter);
     2084//
     2085//                                                                       if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) {
     2086//                                                                               helper.CopyVector(&NewNormalVector);
     2087//                                                                               cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl;
     2088//                                                                               radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter);
     2089//                                                                               if (radius < RADIUS*RADIUS) {
     2090//                                                                                       helper.Scale(sqrt(RADIUS*RADIUS - radius));
     2091//                                                                                       cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl;
     2092//                                                                                       NewSphereCenter.AddVector(&helper);
     2093//                                                                                       NewSphereCenter.SubtractVector(&CircleCenter);
     2094//                                                                                       cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl;
     2095//
     2096//                                                                                       helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction
     2097//                                                                                       OtherNewSphereCenter.AddVector(&helper);
     2098//                                                                                       OtherNewSphereCenter.SubtractVector(&CircleCenter);
     2099//                                                                                       cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl;
     2100//
     2101//                                                                                       // check both possible centers
     2102//                                                                                       alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection);
     2103//                                                                                       Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection);
     2104//                                                                                       alpha = min(alpha, Otheralpha);
     2105//                                                                                       if (*ShortestAngle > alpha) {
     2106//                                                                                                       OptCandidate = Candidate;
     2107//                                                                                                       *ShortestAngle = alpha;
     2108//                                                                                                       if (alpha != Otheralpha)
     2109//                                                                                                               OptCandidateCenter->CopyVector(&NewSphereCenter);
     2110//                                                                                                       else
     2111//                                                                                                               OptCandidateCenter->CopyVector(&OtherNewSphereCenter);
     2112//                                                                                                       cout << Verbose(1) << "We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl;
     2113//                                                                                       } else {
     2114//                                                                                               if (OptCandidate != NULL)
     2115//                                                                                                       cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl;
     2116//                                                                                               else
     2117//                                                                                                       cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl;
     2118//                                                                                       }
     2119//
     2120//                                                                               } else {
     2121//                                                                                       cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl;
     2122//                                                                               }
     2123//                                                                       } else {
     2124//                                                                               cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl;
     2125//                                                                       }
     2126//                                                               } else {
     2127//                                                                       cout << Verbose(1) << "REJECT: Base triangle " << *BaseTriangle << " contains Candidate " << *Candidate << "." << endl;
     2128//                                                               }
     2129//                                                       }
     2130//                                               }
     2131//                                       }
     2132//               } else {
     2133//                       cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
     2134//               }
     2135//       } else {
     2136//               cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and base triangle " << *BaseTriangle << " is too big!" << endl;
     2137//       }
     2138//
     2139//       cout << Verbose(1) << "End of Find_next_suitable_point" << endl;
     2140// };
     2141
     2142
     2143/** Checks whether the triangle consisting of the three atoms is already present.
     2144 * Searches for the points in Tesselation::PointsOnBoundary and checks their
     2145 * lines. If any of the three edges already has two triangles attached, false is
     2146 * returned.
     2147 * \param *out output stream for debugging
     2148 * \param *Candidates endpoints of the triangle candidate
     2149 * \return false - triangle invalid due to edge criteria, true - triangle may be added.
     2150 */
     2151bool Tesselation::CheckPresenceOfTriangle(ofstream *out, atom *Candidates[3]) {
     2152        LineMap::iterator FindLine;
     2153        PointMap::iterator FindPoint;
     2154        bool Present[3];
     2155
     2156        *out << Verbose(2) << "Begin of CheckPresenceOfTriangle" << endl;
     2157        for (int i=0;i<3;i++) { // check through all endpoints
     2158                FindPoint = PointsOnBoundary.find(Candidates[i]->nr);
     2159                if (FindPoint != PointsOnBoundary.end())
     2160                        TPS[i] = FindPoint->second;
     2161                else
     2162                        TPS[i] = NULL;
     2163        }
     2164
     2165        // check lines
     2166        for (int i=0;i<3;i++)
     2167                if (TPS[i] != NULL)
     2168                        for (int j=i;j<3;j++)
     2169                                if (TPS[j] != NULL) {
     2170                                        FindLine = TPS[i]->lines.find(TPS[j]->node->nr);
     2171                                        if ((FindLine != TPS[i]->lines.end()) && (FindLine->second->TrianglesCount > 1)) {
     2172                                                *out << "WARNING: Line " << *FindLine->second << " already present with " << FindLine->second->TrianglesCount << " triangles attached." << endl;
     2173                                                *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;
     2174                                                return false;
     2175                                        }
     2176                                }
     2177        *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;
     2178        return true;
     2179};
     2180
     2181/** This recursive function finds a third point, to form a triangle with two given ones.
     2182 * Note that this function is for the starting triangle.
     2183 * The idea is as follows: A sphere with fixed radius is (almost) uniquely defined in space by three points
     2184 * that sit on its boundary. Hence, when two points are given and we look for the (next) third point, then
     2185 * the center of the sphere is still fixed up to a single parameter. The band of possible values
     2186 * describes a circle in 3D-space. The old center of the sphere for the current base triangle gives
     2187 * us the "null" on this circle, the new center of the candidate point will be some way along this
     2188 * circle. The shorter the way the better is the candidate. Note that the direction is clearly given
     2189 * by the normal vector of the base triangle that always points outwards by construction.
     2190 * Hence, we construct a Center of this circle which sits right in the middle of the current base line.
     2191 * We construct the normal vector that defines the plane this circle lies in, it is just in the
     2192 * direction of the baseline. And finally, we need the radius of the circle, which is given by the rest
     2193 * with respect to the length of the baseline and the sphere's fixed \a RADIUS.
     2194 * Note that there is one difficulty: The circumcircle is uniquely defined, but for the circumsphere's center
     2195 * there are two possibilities which becomes clear from the construction as seen below. Hence, we must check
     2196 * both.
     2197 * Note also that the acos() function is not unique on [0, 2.*M_PI). Hence, we need an additional check
     2198 * to decide for one of the two possible angles. Therefore we need a SearchDirection and to make this check
     2199 * sensible we need OldSphereCenter to be orthogonal to it. Either we construct SearchDirection orthogonal
     2200 * right away, or -- what we do here -- we rotate the relative sphere centers such that this orthogonality
     2201 * holds. Then, the normalized projection onto the SearchDirection is either +1 or -1 and thus states whether
     2202 * the angle is uniquely in either (0,M_PI] or [M_PI, 2.*M_PI).
     2203 * @param NormalVector normal direction of the base triangle (here the unit axis vector, \sa Find_starting_triangle())
     2204 * @param SearchDirection general direction where to search for the next point, relative to center of BaseLine
     2205 * @param OldSphereCenter center of sphere for base triangle, relative to center of BaseLine, giving null angle for the parameter circle
     2206 * @param BaseLine BoundaryLineSet with the current base line
     2207 * @param ThirdNode third atom to avoid in search
     2208 * @param OptCandidate candidate reference on return
     2209 * @param OptCandidateCenter candidate's sphere center on return
     2210 * @param ShortestAngle the current path length on this circle band for the current Opt_Candidate
     2211 * @param RADIUS radius of sphere
     2212 * @param *LC LinkedCell structure with neighbouring atoms
     2213 */
     2214void Find_third_point_for_Tesselation(Vector NormalVector, Vector SearchDirection, Vector OldSphereCenter, class BoundaryLineSet *BaseLine, atom *ThirdNode, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC)
     2215{
     2216        atom *Walker = NULL;
     2217        Vector CircleCenter;    // center of the circle, i.e. of the band of sphere's centers
     2218        Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in
     2219        Vector NewSphereCenter;  // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility
     2220        Vector OtherNewSphereCenter;     // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility
     2221        Vector NewNormalVector;  // normal vector of the Candidate's triangle
     2222        Vector helper;
     2223        LinkedAtoms *List = NULL;
     2224        double CircleRadius; // radius of this circle
     2225        double radius;
     2226        double alpha, Otheralpha; // angles (i.e. parameter for the circle).
     2227        double Nullalpha; // angle between OldSphereCenter and NormalVector of base triangle
     2228        int N[NDIM], Nlower[NDIM], Nupper[NDIM];
     2229        atom *Candidate = NULL;
     2230
     2231        cout << Verbose(1) << "Begin of Find_third_point_for_Tesselation" << endl;
     2232
     2233        cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl;
     2234
     2235        // construct center of circle
     2236        CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x));
     2237        CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x);
     2238        CircleCenter.Scale(0.5);
     2239
     2240        // construct normal vector of circle
     2241        CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x);
     2242        CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x);
     2243
     2244        // calculate squared radius of circle
     2245        radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
     2246        if (radius/4. < RADIUS*RADIUS) {
     2247                CircleRadius = RADIUS*RADIUS - radius/4.;
     2248                CirclePlaneNormal.Normalize();
     2249                cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
     2250
     2251                // test whether old center is on the band's plane
     2252                if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
     2253                        cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl;
     2254                        OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal);
     2255                }
     2256                radius = OldSphereCenter.ScalarProduct(&OldSphereCenter);
     2257                if (fabs(radius - CircleRadius) < HULLEPSILON) {
     2258
     2259                        // check SearchDirection
     2260                        cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
     2261                        if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {      // rotated the wrong way!
     2262                                cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are not orthogonal!" << endl;
     2263                        }
     2264                        // get cell for the starting atom
     2265                        if (LC->SetIndexToVector(&CircleCenter)) {
     2266                                        for(int i=0;i<NDIM;i++) // store indices of this cell
     2267                                        N[i] = LC->n[i];
     2268                                cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
     2269                        } else {
     2270                                cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl;
     2271                                return;
     2272                        }
     2273                        // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
     2274                        cout << Verbose(2) << "LC Intervals:";
     2275                        for (int i=0;i<NDIM;i++) {
     2276                                Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
     2277                                Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
     2278                                cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
     2279                        }
     2280                        cout << endl;
     2281                        for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
     2282                                for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
     2283                                        for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
     2284                                                List = LC->GetCurrentCell();
     2285                                                //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
     2286                                                if (List != NULL) {
     2287                                                        for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
     2288                                                                Candidate = (*Runner);
     2289
     2290                                                                // check for three unique points
     2291                                                                if ((Candidate != BaseLine->endpoints[0]->node) && (Candidate != BaseLine->endpoints[1]->node) && (Candidate != ThirdNode)) {
     2292                                                                        cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl;
     2293
     2294                                                                        // construct both new centers
     2295                                                                        GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x));
     2296                                                                        OtherNewSphereCenter.CopyVector(&NewSphereCenter);
     2297
     2298                                                                        if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) {
     2299                                                                                helper.CopyVector(&NewNormalVector);
     2300                                                                                cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl;
     2301                                                                                radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter);
     2302                                                                                if (radius < RADIUS*RADIUS) {
     2303                                                                                        helper.Scale(sqrt(RADIUS*RADIUS - radius));
     2304                                                                                        cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl;
     2305                                                                                        NewSphereCenter.AddVector(&helper);
     2306                                                                                        NewSphereCenter.SubtractVector(&CircleCenter);
     2307                                                                                        cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl;
     2308
     2309                                                                                        helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction
     2310                                                                                        OtherNewSphereCenter.AddVector(&helper);
     2311                                                                                        OtherNewSphereCenter.SubtractVector(&CircleCenter);
     2312                                                                                        cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl;
     2313
     2314                                                                                        // check both possible centers
     2315                                                                                        alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, NormalVector, SearchDirection);
     2316                                                                                        Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, NormalVector, SearchDirection);
     2317                                                                                        alpha = min(alpha, Otheralpha);
     2318                                                                                        if (*ShortestAngle > alpha) {
     2319                                                                                                        OptCandidate = Candidate;
     2320                                                                                                        *ShortestAngle = alpha;
     2321                                                                                                        if (alpha != Otheralpha)
     2322                                                                                                                OptCandidateCenter->CopyVector(&NewSphereCenter);
     2323                                                                                                        else
     2324                                                                                                                OptCandidateCenter->CopyVector(&OtherNewSphereCenter);
     2325                                                                                                        cout << Verbose(1) << "ACCEPT: We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl;
     2326                                                                                        } else {
     2327                                                                                                if (OptCandidate != NULL)
     2328                                                                                                        cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl;
     2329                                                                                                else
     2330                                                                                                        cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl;
     2331                                                                                        }
     2332
     2333                                                                                } else {
     2334                                                                                        cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl;
     2335                                                                                }
     2336                                                                        } else {
     2337                                                                                cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl;
     2338                                                                        }
     2339                                                                } else {
     2340                                                                        if (ThirdNode != NULL)
     2341                                                                                cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " and " << *ThirdNode << " contains Candidate " << *Candidate << "." << endl;
     2342                                                                        else
     2343                                                                                cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " contains Candidate " << *Candidate << "." << endl;
     2344                                                                }
     2345                                                        }
     2346                                                }
     2347                                        }
     2348                } else {
     2349                        cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
     2350                }
     2351        } else {
     2352                if (ThirdNode != NULL)
     2353                        cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and third node " << *ThirdNode << " is too big!" << endl;
     2354                else
     2355                        cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " is too big!" << endl;
     2356        }
     2357
     2358        cout << Verbose(1) << "End of Find_third_point_for_Tesselation" << endl;
     2359};
     2360
     2361/** Finds the second point of starting triangle.
     2362 * \param *a first atom
     2363 * \param *Candidate pointer to candidate atom on return
     2364 * \param Oben vector indicating the outside
     2365 * \param Opt_Candidate reference to recommended candidate on return
     2366 * \param Storage[3] array storing angles and other candidate information
     2367 * \param RADIUS radius of virtual sphere
     2368 * \param *LC LinkedCell structure with neighbouring atoms
     2369 */
     2370void Find_second_point_for_Tesselation(atom* a, atom* Candidate, Vector Oben, atom*& Opt_Candidate, double Storage[3], double RADIUS, LinkedCell *LC)
     2371{
     2372        cout << Verbose(2) << "Begin of Find_second_point_for_Tesselation" << endl;
     2373        int i;
     2374        Vector AngleCheck;
     2375        atom* Walker;
     2376        double norm = -1., angle;
     2377        LinkedAtoms *List = NULL;
     2378        int N[NDIM], Nlower[NDIM], Nupper[NDIM];
     2379
     2380        if (LC->SetIndexToAtom(a)) {    // get cell for the starting atom
     2381                for(int i=0;i<NDIM;i++) // store indices of this cell
     2382                        N[i] = LC->n[i];
     2383        } else {
     2384                cerr << "ERROR: Atom " << *a << " is not found in cell " << LC->index << "." << endl;
     2385                return;
     2386        }
     2387        // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
     2388        cout << Verbose(2) << "LC Intervals:";
     2389        for (int i=0;i<NDIM;i++) {
     2390                Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
     2391                Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
     2392                cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
     2393        }
     2394        cout << endl;
     2395        for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
     2396                for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
     2397                        for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
     2398                                List = LC->GetCurrentCell();
     2399                                //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
     2400                                if (List != NULL) {
     2401                                        for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
     2402                                                Candidate = (*Runner);
     2403                                                                // check if we only have one unique point yet ...
     2404                                                                if (a != Candidate) {
     2405                        cout << Verbose(3) << "Current candidate is " << *Candidate << ": ";
     2406                        AngleCheck.CopyVector(&(Candidate->x));
     2407                        AngleCheck.SubtractVector(&(a->x));
     2408                        norm = AngleCheck.Norm();
     2409                                                        // second point shall have smallest angle with respect to Oben vector
     2410                                                        if (norm < RADIUS) {
     2411                                                                angle = AngleCheck.Angle(&Oben);
     2412                                                                if (angle < Storage[0]) {
     2413                                                                        //cout << Verbose(1) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[1]);
     2414                                                                        cout << "Is a better candidate with distance " << norm << " and " << angle << ".\n";
     2415                                                                        Opt_Candidate = Candidate;
     2416                                                                        Storage[0] = AngleCheck.Angle(&Oben);
     2417                                                                        //cout << Verbose(1) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[2]);
     2418                                                                } else {
     2419                                                                        cout << "Looses with angle " << angle << " to a better candidate " << *Opt_Candidate << endl;
     2420                                                                }
     2421                                                        } else {
     2422                                                                cout << "Refused due to Radius " << norm << endl;
     2423                                                        }
     2424                                                }
     2425                                        }
     2426                                }
     2427                        }
     2428        cout << Verbose(2) << "End of Find_second_point_for_Tesselation" << endl;
     2429};
     2430
     2431/** Finds the starting triangle for find_non_convex_border().
     2432 * Looks at the outermost atom per axis, then Find_second_point_for_Tesselation()
     2433 * for the second and Find_next_suitable_point_via_Angle_of_Sphere() for the third
     2434 * point are called.
     2435 * \param RADIUS radius of virtual rolling sphere
     2436 * \param *LC LinkedCell structure with neighbouring atoms
     2437 */
     2438void Tesselation::Find_starting_triangle(ofstream *out, molecule *mol, const double RADIUS, LinkedCell *LC)
     2439{
     2440        cout << Verbose(1) << "Begin of Find_starting_triangle\n";
     2441        int i = 0;
     2442        LinkedAtoms *List = NULL;
     2443        atom* Walker;
     2444        atom* FirstPoint;
     2445        atom* SecondPoint;
     2446        atom* MaxAtom[NDIM];
     2447        double max_coordinate[NDIM];
     2448        Vector Oben;
     2449        Vector helper;
     2450        Vector Chord;
     2451        Vector SearchDirection;
     2452        Vector OptCandidateCenter;
     2453
     2454        Oben.Zero();
     2455
     2456        for (i = 0; i < 3; i++) {
     2457                MaxAtom[i] = NULL;
     2458                max_coordinate[i] = -1;
     2459        }
     2460
     2461        // 1. searching topmost atom with respect to each axis
     2462        for (int i=0;i<NDIM;i++) { // each axis
     2463                LC->n[i] = LC->N[i]-1; // current axis is topmost cell
     2464                for (LC->n[(i+1)%NDIM]=0;LC->n[(i+1)%NDIM]<LC->N[(i+1)%NDIM];LC->n[(i+1)%NDIM]++)
     2465                        for (LC->n[(i+2)%NDIM]=0;LC->n[(i+2)%NDIM]<LC->N[(i+2)%NDIM];LC->n[(i+2)%NDIM]++) {
     2466                                List = LC->GetCurrentCell();
     2467                                //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
     2468                                if (List != NULL) {
     2469                                        for (LinkedAtoms::iterator Runner = List->begin();Runner != List->end();Runner++) {
     2470                                                cout << Verbose(2) << "Current atom is " << *(*Runner) << "." << endl;
     2471                                                if ((*Runner)->x.x[i] > max_coordinate[i]) {
     2472                                                        max_coordinate[i] = (*Runner)->x.x[i];
     2473                                                        MaxAtom[i] = (*Runner);
     2474                                                }
     2475                                        }
     2476                                } else {
     2477                                        cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << " is invalid!" << endl;
     2478                                }
     2479                        }
     2480        }
     2481
     2482        cout << Verbose(2) << "Found maximum coordinates: ";
     2483        for (int i=0;i<NDIM;i++)
     2484                cout << i << ": " << *MaxAtom[i] << "\t";
     2485        cout << endl;
     2486        const int k = 1;                // arbitrary choice
     2487        Oben.x[k] = 1.;
     2488        FirstPoint = MaxAtom[k];
     2489        cout << Verbose(1) << "Coordinates of start atom " << *FirstPoint << " at " << FirstPoint->x << "." << endl;
     2490
     2491        // add first point
     2492        AddTrianglePoint(FirstPoint, 0);
     2493
     2494        double ShortestAngle;
     2495        atom* Opt_Candidate = NULL;
     2496        ShortestAngle = 999999.; // This will contain the angle, which will be always positive (when looking for second point), when looking for third point this will be the quadrant.
     2497
     2498        Find_second_point_for_Tesselation(FirstPoint, NULL, Oben, Opt_Candidate, &ShortestAngle, RADIUS, LC); // we give same point as next candidate as its bonds are looked into in find_second_...
     2499        SecondPoint = Opt_Candidate;
     2500        cout << Verbose(1) << "Found second point is " << *SecondPoint << " at " << SecondPoint->x << ".\n";
     2501
     2502        // add second point and first baseline
     2503        AddTrianglePoint(SecondPoint, 1);
     2504        AddTriangleLine(TPS[0], TPS[1], 0);
     2505
     2506        helper.CopyVector(&(FirstPoint->x));
     2507        helper.SubtractVector(&(SecondPoint->x));
     2508        helper.Normalize();
     2509        Oben.ProjectOntoPlane(&helper);
     2510        Oben.Normalize();
     2511        helper.VectorProduct(&Oben);
     2512        ShortestAngle = 2.*M_PI; // This will indicate the quadrant.
     2513
     2514        Chord.CopyVector(&(FirstPoint->x)); // bring into calling function
     2515        Chord.SubtractVector(&(SecondPoint->x));
     2516        double radius = Chord.ScalarProduct(&Chord);
     2517        double CircleRadius = sqrt(RADIUS*RADIUS - radius/4.);
     2518        helper.CopyVector(&Oben);
     2519        helper.Scale(CircleRadius);
     2520        // Now, oben and helper are two orthonormalized vectors in the plane defined by Chord (not normalized)
     2521
     2522        cout << Verbose(2) << "Looking for third point candidates \n";
     2523        // look in one direction of baseline for initial candidate
     2524        Opt_Candidate = NULL;
     2525        SearchDirection.MakeNormalVector(&Chord, &Oben);        // whether we look "left" first or "right" first is not important ...
     2526
     2527        cout << Verbose(1) << "Looking for third point candidates ...\n";
     2528        Find_third_point_for_Tesselation(Oben, SearchDirection, helper, BLS[0], NULL, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC);
     2529        cout << Verbose(1) << "Third Point is " << *Opt_Candidate << endl;
     2530
     2531        // add third point
     2532        AddTrianglePoint(Opt_Candidate, 2);
     2533
     2534        // FOUND Starting Triangle: FirstPoint, SecondPoint, Opt_Candidate
     2535
     2536        // Finally, we only have to add the found further lines
     2537        AddTriangleLine(TPS[1], TPS[2], 1);
     2538        AddTriangleLine(TPS[0], TPS[2], 2);
     2539        // ... and triangles to the Maps of the Tesselation class
     2540        BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     2541        AddTriangleToLines();
     2542        // ... and calculate its normal vector (with correct orientation)
     2543        OptCandidateCenter.Scale(-1.);
     2544        cout << Verbose(2) << "Oben is currently " << OptCandidateCenter << "." << endl;
     2545        BTS->GetNormalVector(OptCandidateCenter);
     2546        cout << Verbose(0) << "==> The found starting triangle consists of " << *FirstPoint << ", " << *SecondPoint << " and " << *Opt_Candidate << " with normal vector " << BTS->NormalVector << ".\n";
     2547        cout << Verbose(2) << "Projection is " << BTS->NormalVector.Projection(&Oben) << "." << endl;
     2548        cout << Verbose(1) << "End of Find_starting_triangle\n";
     2549};
    19802550
    19812551/** This function finds a triangle to a line, adjacent to an existing one.
    1982  * @param out   output stream for debugging
    1983  * @param mol molecule structure with all atoms and bonds
     2552 * @param out output stream for debugging
     2553 * @param *mol molecule with Atom's and Bond's
    19842554 * @param Line current baseline to search from
    19852555 * @param T current triangle which \a Line is edge of
    19862556 * @param RADIUS radius of the rolling ball
    19872557 * @param N number of found triangles
     2558 * @param *filename filename base for intermediate envelopes
     2559 * @param *LC LinkedCell structure with neighbouring atoms
    19882560 */
    1989 void Tesselation::Find_next_suitable_triangle(ofstream *out,
    1990     molecule* mol, BoundaryLineSet &Line, BoundaryTriangleSet &T,
    1991     const double& RADIUS, int N, const char *tempbasename)
    1992 {
    1993   cout << Verbose(1) << "Looking for next suitable triangle \n";
    1994   Vector direction1;
    1995   Vector helper;
    1996   Vector Chord;
    1997   ofstream *tempstream = NULL;
    1998   char NumberName[255];
    1999   double tmp;
    2000   //atom* Walker;
    2001   atom* OldThirdPoint;
    2002 
    2003   double Storage[3];
    2004   Storage[0] = -2.; // This direction is either +1 or -1 one, so any result will take precedence over initial values
    2005   Storage[1] = -2.; // This is also lower then any value produced by an eligible atom, which are all positive
    2006   Storage[2] = 9999999.;
    2007   atom* Opt_Candidate = NULL;
    2008   Vector Opt_Mittelpunkt;
    2009 
    2010   cout << Verbose(1) << "Constructing helpful vectors ... " << endl;
    2011   helper.CopyVector(&(Line.endpoints[0]->node->x));
    2012   for (int i = 0; i < 3; i++)
    2013     {
    2014       if (T.endpoints[i]->node->nr != Line.endpoints[0]->node->nr
    2015           && T.endpoints[i]->node->nr != Line.endpoints[1]->node->nr)
    2016         {
    2017           OldThirdPoint = T.endpoints[i]->node;
    2018           helper.SubtractVector(&T.endpoints[i]->node->x);
    2019           break;
    2020         }
    2021     }
    2022 
    2023   direction1.CopyVector(&Line.endpoints[0]->node->x);
    2024   direction1.SubtractVector(&Line.endpoints[1]->node->x);
    2025   direction1.VectorProduct(&(T.NormalVector));
    2026 
    2027   if (direction1.ScalarProduct(&helper) < 0)
    2028     {
    2029       direction1.Scale(-1);
    2030     }
    2031 
    2032   Chord.CopyVector(&(Line.endpoints[0]->node->x)); // bring into calling function
    2033   Chord.SubtractVector(&(Line.endpoints[1]->node->x));
    2034 
    2035 
    2036     Vector Umkreismittelpunkt, a, b, c;
    2037     double alpha, beta, gamma;
    2038     a.CopyVector(&(T.endpoints[0]->node->x));
    2039     b.CopyVector(&(T.endpoints[1]->node->x));
    2040     c.CopyVector(&(T.endpoints[2]->node->x));
    2041     a.SubtractVector(&(T.endpoints[1]->node->x));
    2042     b.SubtractVector(&(T.endpoints[2]->node->x));
    2043     c.SubtractVector(&(T.endpoints[0]->node->x));
    2044 
    2045     alpha = M_PI - a.Angle(&c);
    2046     beta = M_PI - b.Angle(&a);
    2047     gamma = M_PI - c.Angle(&b);
    2048 
    2049     Umkreismittelpunkt = (T.endpoints[0]->node->x) * sin(2.*alpha) + T.endpoints[1]->node->x * sin(2.*beta) + (T.endpoints[2]->node->x) * sin(2.*gamma) ;
    2050     //cout << "UmkreisMittelpunkt is " << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] << " "<< Umkreismittelpunkt.x[2] << " "<< endl;
    2051     Umkreismittelpunkt.Scale(1/(sin(2*alpha) + sin(2*beta) + sin(2*gamma)));
    2052     cout << "UmkreisMittelpunkt is " << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] << " "<< Umkreismittelpunkt.x[2] << " "<< endl;
    2053     cout << " We look over line " << Line << " in direction " << direction1.x[0] << " " << direction1.x[1] << " " << direction1.x[2] << " " << endl;
    2054     cout << " Old Normal is " <<  (T.NormalVector.x)[0] << " " << T.NormalVector.x[1] << " " << (T.NormalVector.x)[2] << " " << endl;
    2055 
    2056 
    2057   cout << Verbose(1) << "Looking for third point candidates for triangle ... " << endl;
    2058 
    2059   Find_next_suitable_point_via_Angle_of_Sphere(Line.endpoints[0]->node, Line.endpoints[1]->node, OldThirdPoint,
    2060       Line.endpoints[0]->node, Line.endpoints[1]->node, 0, &Chord, &direction1,
    2061       &(T.NormalVector), Umkreismittelpunkt, Opt_Candidate, Storage, RADIUS, mol);
    2062   Find_next_suitable_point_via_Angle_of_Sphere(Line.endpoints[0]->node, Line.endpoints[1]->node, OldThirdPoint,
    2063       Line.endpoints[1]->node, Line.endpoints[0]->node, 0, &Chord, &direction1,
    2064       &(T.NormalVector), Umkreismittelpunkt, Opt_Candidate, Storage, RADIUS, mol);
    2065 
    2066 
    2067       cout << "Letzter Winkel bei " << TrianglesOnBoundaryCount << " Winkel ist " << Storage[2] << endl;
    2068 
    2069   if ((TrianglesOnBoundaryCount % 10) == 0) {
    2070     sprintf(NumberName, "-%d", TriangleFilesWritten);
    2071     if (DoTecplotOutput) {
    2072       string NameofTempFile(tempbasename);
    2073       NameofTempFile.append(NumberName);
    2074       NameofTempFile.append(TecplotSuffix);
    2075       cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
    2076       tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
    2077       write_tecplot_file(out, tempstream, this, mol, TriangleFilesWritten);
    2078       tempstream->close();
    2079       tempstream->flush();
    2080       delete(tempstream);
    2081     }
    2082     if (DoRaster3DOutput) {
    2083       string NameofTempFile(tempbasename);
    2084       NameofTempFile.append(NumberName);
    2085       NameofTempFile.append(Raster3DSuffix);
    2086       cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
    2087       tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
    2088       write_raster3d_file(out, tempstream, this, mol);
    2089       tempstream->close();
    2090       tempstream->flush();
    2091       delete(tempstream);
    2092     }
    2093     if (DoTecplotOutput || DoRaster3DOutput)
    2094       TriangleFilesWritten++;
    2095   }
    2096 
    2097       // Konstruiere nun neues Dreieck am Ende der Liste der Dreiecke
    2098 
    2099   cout << " Optimal candidate is " << *Opt_Candidate << endl;
    2100 
    2101   AddTrianglePoint(Opt_Candidate, 0);
    2102   AddTrianglePoint(Line.endpoints[0]->node, 1);
    2103   AddTrianglePoint(Line.endpoints[1]->node, 2);
    2104 
    2105   AddTriangleLine(TPS[0], TPS[1], 0);
    2106   AddTriangleLine(TPS[0], TPS[2], 1);
    2107   AddTriangleLine(TPS[1], TPS[2], 2);
    2108 
    2109   BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    2110   AddTriangleToLines();
    2111   cout << "New triangle with " << *BTS << endl;
    2112   cout << "We have "<< TrianglesOnBoundaryCount << endl;
    2113   cout << Verbose(1) << "Constructing normal vector for this triangle ... " << endl;
    2114 
    2115   BTS->GetNormalVector(BTS->NormalVector);
    2116 
    2117   if ((BTS->NormalVector.ScalarProduct(&(T.NormalVector)) < 0 && Storage[0] > 0)  ||
    2118       (BTS->NormalVector.ScalarProduct(&(T.NormalVector)) > 0 && Storage[0] < 0) ||
    2119       (fabs(Storage[0]) < MYEPSILON && Storage[1]*BTS->NormalVector.ScalarProduct(&direction1) < 0) )
    2120 
    2121     {
    2122       BTS->NormalVector.Scale(-1);
    2123     };
    2124 
    2125 }
    2126 ;
    2127 
    2128 void Find_second_point_for_Tesselation(atom* a, atom* Candidate, atom* Parent,
    2129     int RecursionLevel, Vector Oben, atom*& Opt_Candidate, double Storage[3],
    2130     molecule* mol, double RADIUS)
    2131 {
    2132   cout << Verbose(1)
    2133       << "Looking for second point of starting triangle, recursive level "
    2134       << RecursionLevel << endl;;
    2135   int i;
    2136   Vector AngleCheck;
    2137   atom* Walker;
    2138   double norm = -1.;
    2139 
    2140   // check if we only have one unique point yet ...
    2141   if (a != Candidate)
    2142     {
    2143       AngleCheck.CopyVector(&(Candidate->x));
    2144       AngleCheck.SubtractVector(&(a->x));
    2145       norm = AngleCheck.Norm();
    2146       // second point shall have smallest angle with respect to Oben vector
    2147       if (norm < RADIUS)
    2148         {
    2149           if (AngleCheck.Angle(&Oben) < Storage[0])
    2150             {
    2151               //cout << Verbose(1) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[2]);
    2152               cout << "Next better candidate is " << *Candidate
    2153                   << " with distance " << norm << ".\n";
    2154               Opt_Candidate = Candidate;
    2155               Storage[0] = AngleCheck.Angle(&Oben);
    2156               //cout << Verbose(1) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[2]);
    2157             }
    2158           else
    2159             {
    2160               cout << Verbose(1) << "Supposedly looses to a better candidate "
    2161                   << *Opt_Candidate << endl;
    2162             }
    2163         }
    2164       else
    2165         {
    2166           cout << Verbose(1) << *Candidate << " refused due to Radius " << norm
    2167               << endl;
    2168         }
    2169     }
    2170 
    2171   // if not recursed to deeply, look at all its bonds
    2172   if (RecursionLevel < 7)
    2173     {
    2174       for (i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++)
    2175         {
    2176           Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(
    2177               Candidate);
    2178           if (Walker == Parent) // don't go back along the bond we came from
    2179             continue;
    2180           else
    2181             Find_second_point_for_Tesselation(a, Walker, Candidate,
    2182                 RecursionLevel + 1, Oben, Opt_Candidate, Storage, mol, RADIUS);
    2183         };
    2184     };
    2185 }
    2186 ;
    2187 
    2188 void Tesselation::Find_starting_triangle(molecule* mol, const double RADIUS)
    2189 {
    2190   cout << Verbose(1) << "Looking for starting triangle \n";
    2191   int i = 0;
    2192   atom* Walker;
    2193   atom* FirstPoint;
    2194   atom* SecondPoint;
    2195   atom* max_index[3];
    2196   double max_coordinate[3];
    2197   Vector Oben;
    2198   Vector helper;
    2199   Vector Chord;
    2200   Vector CenterOfFirstLine;
    2201 
    2202   Oben.Zero();
    2203 
    2204   for (i = 0; i < 3; i++)
    2205     {
    2206       max_index[i] = NULL;
    2207       max_coordinate[i] = -1;
    2208     }
    2209   cout << Verbose(1) << "Molecule mol is there and has " << mol->AtomCount
    2210       << " Atoms \n";
    2211 
    2212   // 1. searching topmost atom with respect to each axis
    2213   Walker = mol->start;
    2214   while (Walker->next != mol->end)
    2215     {
    2216       Walker = Walker->next;
    2217       for (i = 0; i < 3; i++)
    2218         {
    2219           if (Walker->x.x[i] > max_coordinate[i])
    2220             {
    2221               max_coordinate[i] = Walker->x.x[i];
    2222               max_index[i] = Walker;
    2223             }
    2224         }
    2225     }
    2226 
    2227   cout << Verbose(1) << "Found maximum coordinates. " << endl;
    2228   //Koennen dies fuer alle Richtungen, legen hier erstmal Richtung auf k=0
    2229   const int k = 1;
    2230   Oben.x[k] = 1.;
    2231   FirstPoint = max_index[k];
    2232 
    2233   cout << Verbose(1) << "Coordinates of start atom " << *FirstPoint << ": "
    2234       << FirstPoint->x.x[0] << endl;
    2235   double Storage[3];
    2236   atom* Opt_Candidate = NULL;
    2237   Storage[0] = 999999.; // This will contain the angle, which will be always positive (when looking for second point), when looking for third point this will be the quadrant.
    2238   Storage[1] = 999999.; // This will be an angle looking for the third point.
    2239   Storage[2] = 999999.;
    2240   cout << Verbose(1) << "Number of Bonds: "
    2241       << mol->NumberOfBondsPerAtom[FirstPoint->nr] << endl;
    2242 
    2243   Find_second_point_for_Tesselation(FirstPoint, FirstPoint, FirstPoint, 0,
    2244       Oben, Opt_Candidate, Storage, mol, RADIUS); // we give same point as next candidate as its bonds are looked into in find_second_...
    2245   SecondPoint = Opt_Candidate;
    2246   cout << Verbose(1) << "Found second point is " << *SecondPoint << ".\n";
    2247 
    2248   helper.CopyVector(&(FirstPoint->x));
    2249   helper.SubtractVector(&(SecondPoint->x));
    2250   helper.Normalize();
    2251   Oben.ProjectOntoPlane(&helper);
    2252   Oben.Normalize();
    2253   helper.VectorProduct(&Oben);
    2254   Storage[0] = -2.; // This will indicate the quadrant.
    2255   Storage[1] = 9999999.; // This will be an angle looking for the third point.
    2256   Storage[2] = 9999999.;
    2257 
    2258   Chord.CopyVector(&(FirstPoint->x)); // bring into calling function
    2259   Chord.SubtractVector(&(SecondPoint->x));
    2260   // Now, oben and helper are two orthonormalized vectors in the plane defined by Chord (not normalized)
    2261 
    2262   cout << Verbose(1) << "Looking for third point candidates \n";
    2263   cout << Verbose(1) << " In direction " << helper.x[0] << " " << helper.x[1] << " " << helper.x[2] << " " << endl;
    2264   // look in one direction of baseline for initial candidate
    2265   Opt_Candidate = NULL;
    2266   CenterOfFirstLine.CopyVector(&Chord);
    2267   CenterOfFirstLine.Scale(0.5);
    2268   CenterOfFirstLine.AddVector(&(SecondPoint->x));
    2269 
    2270   Find_next_suitable_point_via_Angle_of_Sphere(FirstPoint, SecondPoint, SecondPoint, SecondPoint, FirstPoint, 0,
    2271       &Chord, &helper, &Oben, CenterOfFirstLine,  Opt_Candidate, Storage, RADIUS, mol);
    2272   // look in other direction of baseline for possible better candidate
    2273   Find_next_suitable_point_via_Angle_of_Sphere(FirstPoint, SecondPoint, SecondPoint, FirstPoint, SecondPoint, 0,
    2274       &Chord, &helper, &Oben, CenterOfFirstLine, Opt_Candidate, Storage, RADIUS, mol);
    2275   cout << Verbose(1) << "Third Point is " << *Opt_Candidate << endl;
    2276 
    2277   // FOUND Starting Triangle: FirstPoint, SecondPoint, Opt_Candidate
    2278 
    2279   cout << Verbose(1) << "The found starting triangle consists of "
    2280       << *FirstPoint << ", " << *SecondPoint << " and " << *Opt_Candidate
    2281       << "." << endl;
    2282 
    2283   // Finally, we only have to add the found points
    2284   AddTrianglePoint(FirstPoint, 0);
    2285   AddTrianglePoint(SecondPoint, 1);
    2286   AddTrianglePoint(Opt_Candidate, 2);
    2287   // ... and respective lines
    2288   AddTriangleLine(TPS[0], TPS[1], 0);
    2289   AddTriangleLine(TPS[1], TPS[2], 1);
    2290   AddTriangleLine(TPS[0], TPS[2], 2);
    2291   // ... and triangles to the Maps of the Tesselation class
    2292   BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    2293   AddTriangleToLines();
    2294   // ... and calculate its normal vector (with correct orientation)
    2295   Oben.Scale(-1.);
    2296   BTS->GetNormalVector(Oben);
    2297 }
    2298 ;
    2299 
    2300 void Find_non_convex_border(ofstream *out, const char *filename, molecule* mol)
    2301 {
    2302   int N = 0;
    2303   struct Tesselation *Tess = new Tesselation;
    2304   cout << Verbose(1) << "Entering search for non convex hull. " << endl;
    2305   cout << flush;
    2306   const double RADIUS = 6.;
    2307   LineMap::iterator baseline;
    2308   cout << Verbose(0) << "Begin of Find_non_convex_border\n";
    2309   bool flag = false;  // marks whether we went once through all baselines without finding any without two triangles
    2310 
    2311   if ((mol->first->next == mol->last) || (mol->last->previous == mol->first))
    2312     mol->CreateAdjacencyList((ofstream *)&cout, 1.6, true);
    2313 
    2314   Tess->Find_starting_triangle(mol, RADIUS);
    2315 
    2316   baseline = Tess->LinesOnBoundary.begin();
    2317   while (baseline != Tess->LinesOnBoundary.end())
    2318     {
    2319       if (baseline->second->TrianglesCount == 1)
    2320         {
    2321           cout << Verbose(1) << "Begin of Tesselation ... " << endl;
    2322           Tess->Find_next_suitable_triangle(out, mol,
    2323               *(baseline->second),
    2324               *(((baseline->second->triangles.begin()))->second), RADIUS, N, filename); //the line is there, so there is a triangle, but only one.
    2325           flag = true;
    2326           cout << Verbose(1) << "End of Tesselation ... " << endl;
    2327         }
    2328       else
    2329         {
    2330           cout << Verbose(1) << "There is a line with "
    2331               << baseline->second->TrianglesCount << " triangles adjacent"
    2332               << endl;
    2333         }
    2334       N++;
    2335       baseline++;
    2336     }
    2337   cout << Verbose(1) << "Writing final tecplot file\n";
    2338   if (DoTecplotOutput) {
    2339     string Name(filename);
    2340     Name.append(TecplotSuffix);
    2341     ofstream tecplot(Name.c_str(), ios::trunc);
    2342     write_tecplot_file(out, &tecplot, Tess, mol, -1);
    2343     tecplot.close();
    2344   }
    2345   if (DoRaster3DOutput) {
    2346     string Name(filename);
    2347     Name.append(Raster3DSuffix);
    2348     ofstream raster(Name.c_str(), ios::trunc);
    2349     write_raster3d_file(out, &raster, Tess, mol);
    2350     raster.close();
    2351   }
    2352 }
    2353 ;
     2561bool Tesselation::Find_next_suitable_triangle(ofstream *out,
     2562                molecule *mol, BoundaryLineSet &Line, BoundaryTriangleSet &T,
     2563                const double& RADIUS, int N, const char *tempbasename, LinkedCell *LC)
     2564{
     2565        cout << Verbose(1) << "Begin of Find_next_suitable_triangle\n";
     2566        ofstream *tempstream = NULL;
     2567        char NumberName[255];
     2568        double tmp;
     2569
     2570        atom* Opt_Candidate = NULL;
     2571        Vector OptCandidateCenter;
     2572
     2573        Vector CircleCenter;
     2574        Vector CirclePlaneNormal;
     2575        Vector OldSphereCenter;
     2576        Vector SearchDirection;
     2577        Vector helper;
     2578        atom *ThirdNode = NULL;
     2579        double ShortestAngle = 2.*M_PI; // This will indicate the quadrant.
     2580        double radius, CircleRadius;
     2581
     2582        cout << Verbose(1) << "Current baseline is " << Line << " of triangle " << T << "." << endl;
     2583        for (int i=0;i<3;i++)
     2584                if ((T.endpoints[i]->node != Line.endpoints[0]->node) && (T.endpoints[i]->node != Line.endpoints[1]->node))
     2585                        ThirdNode = T.endpoints[i]->node;
     2586
     2587        // construct center of circle
     2588        CircleCenter.CopyVector(&Line.endpoints[0]->node->x);
     2589        CircleCenter.AddVector(&Line.endpoints[1]->node->x);
     2590        CircleCenter.Scale(0.5);
     2591
     2592        // construct normal vector of circle
     2593        CirclePlaneNormal.CopyVector(&Line.endpoints[0]->node->x);
     2594        CirclePlaneNormal.SubtractVector(&Line.endpoints[1]->node->x);
     2595
     2596        // calculate squared radius of circle
     2597        radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
     2598        if (radius/4. < RADIUS*RADIUS) {
     2599                CircleRadius = RADIUS*RADIUS - radius/4.;
     2600                CirclePlaneNormal.Normalize();
     2601                cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
     2602
     2603                // construct old center
     2604                GetCenterofCircumcircle(&OldSphereCenter, &(T.endpoints[0]->node->x), &(T.endpoints[1]->node->x), &(T.endpoints[2]->node->x));
     2605                helper.CopyVector(&T.NormalVector);     // normal vector ensures that this is correct center of the two possible ones
     2606                radius = Line.endpoints[0]->node->x.DistanceSquared(&OldSphereCenter);
     2607                helper.Scale(sqrt(RADIUS*RADIUS - radius));
     2608                OldSphereCenter.AddVector(&helper);
     2609                OldSphereCenter.SubtractVector(&CircleCenter);
     2610                cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;
     2611
     2612                // construct SearchDirection
     2613                SearchDirection.MakeNormalVector(&T.NormalVector, &CirclePlaneNormal);
     2614                helper.CopyVector(&Line.endpoints[0]->node->x);
     2615                helper.SubtractVector(&ThirdNode->x);
     2616                if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)      // ohoh, SearchDirection points inwards!
     2617                        SearchDirection.Scale(-1.);
     2618                SearchDirection.ProjectOntoPlane(&OldSphereCenter);
     2619                SearchDirection.Normalize();
     2620                cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
     2621                if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {      // rotated the wrong way!
     2622                        cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl;
     2623                }
     2624
     2625                // add third point
     2626                cout << Verbose(1) << "Looking for third point candidates for triangle ... " << endl;
     2627                Find_third_point_for_Tesselation(T.NormalVector, SearchDirection, OldSphereCenter, &Line, ThirdNode, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC);
     2628
     2629        } else {
     2630                cout << Verbose(1) << "Circumcircle for base line " << Line << " and base triangle " << T << " is too big!" << endl;
     2631        }
     2632
     2633        if (Opt_Candidate == NULL) {
     2634                cerr << "WARNING: Could not find a suitable candidate." << endl;
     2635                return false;
     2636        }
     2637        cout << Verbose(1) << " Optimal candidate is " << *Opt_Candidate << " with circumsphere's center at " << OptCandidateCenter << "." << endl;
     2638
     2639        // check whether all edges of the new triangle still have space for one more triangle (i.e. TriangleCount <2)
     2640        atom *AtomCandidates[3];
     2641        AtomCandidates[0] = Opt_Candidate;
     2642        AtomCandidates[1] = Line.endpoints[0]->node;
     2643        AtomCandidates[2] = Line.endpoints[1]->node;
     2644        bool flag = CheckPresenceOfTriangle(out, AtomCandidates);
     2645
     2646        if (flag) { // if so, add
     2647                AddTrianglePoint(Opt_Candidate, 0);
     2648                AddTrianglePoint(Line.endpoints[0]->node, 1);
     2649                AddTrianglePoint(Line.endpoints[1]->node, 2);
     2650
     2651                AddTriangleLine(TPS[0], TPS[1], 0);
     2652                AddTriangleLine(TPS[0], TPS[2], 1);
     2653                AddTriangleLine(TPS[1], TPS[2], 2);
     2654
     2655                BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     2656                AddTriangleToLines();
     2657
     2658                OptCandidateCenter.Scale(-1.);
     2659                BTS->GetNormalVector(OptCandidateCenter);
     2660                OptCandidateCenter.Scale(-1.);
     2661
     2662                cout << "--> New triangle with " << *BTS << " and normal vector " << BTS->NormalVector << " for this triangle ... " << endl;
     2663                cout << Verbose(1) << "We have "<< TrianglesOnBoundaryCount << " for line " << Line << "." << endl;
     2664        } else { // else, yell and do nothing
     2665                cout << Verbose(1) << "This triangle consisting of ";
     2666                cout << *Opt_Candidate << ", ";
     2667                cout << *Line.endpoints[0]->node << " and ";
     2668                cout << *Line.endpoints[1]->node << " ";
     2669                cout << "is invalid!" << endl;
     2670                return false;
     2671        }
     2672
     2673        if (flag && (DoSingleStepOutput && (TrianglesOnBoundaryCount % 10 == 0))) { // if we have a new triangle and want to output each new triangle configuration
     2674                sprintf(NumberName, "-%04d-%s_%s_%s", TriangleFilesWritten, BTS->endpoints[0]->node->Name, BTS->endpoints[1]->node->Name, BTS->endpoints[2]->node->Name);
     2675                if (DoTecplotOutput) {
     2676                        string NameofTempFile(tempbasename);
     2677                        NameofTempFile.append(NumberName);
     2678                        for(size_t npos = NameofTempFile.find_first_of(' '); npos != -1; npos = NameofTempFile.find(' ', npos))
     2679                                NameofTempFile.erase(npos, 1);
     2680                        NameofTempFile.append(TecplotSuffix);
     2681                        cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
     2682                        tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
     2683                        write_tecplot_file(out, tempstream, this, mol, TriangleFilesWritten);
     2684                        tempstream->close();
     2685                        tempstream->flush();
     2686                        delete(tempstream);
     2687                }
     2688
     2689                if (DoRaster3DOutput) {
     2690                        string NameofTempFile(tempbasename);
     2691                        NameofTempFile.append(NumberName);
     2692                        for(size_t npos = NameofTempFile.find_first_of(' '); npos != -1; npos = NameofTempFile.find(' ', npos))
     2693                                NameofTempFile.erase(npos, 1);
     2694                        NameofTempFile.append(Raster3DSuffix);
     2695                        cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
     2696                        tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
     2697                        write_raster3d_file(out, tempstream, this, mol);
     2698                        // include the current position of the virtual sphere in the temporary raster3d file
     2699                        // make the circumsphere's center absolute again
     2700                        helper.CopyVector(&Line.endpoints[0]->node->x);
     2701                        helper.AddVector(&Line.endpoints[1]->node->x);
     2702                        helper.Scale(0.5);
     2703                        OptCandidateCenter.AddVector(&helper);
     2704                        Vector *center = mol->DetermineCenterOfAll(out);
     2705                        OptCandidateCenter.AddVector(center);
     2706                        delete(center);
     2707                        // and add to file plus translucency object
     2708                        *tempstream << "# current virtual sphere\n";
     2709                        *tempstream << "8\n     25.0            0.6              -1.0 -1.0 -1.0          0.2                            0 0 0 0\n";
     2710                        *tempstream << "2\n     " << OptCandidateCenter.x[0] << " " << OptCandidateCenter.x[1] << " " << OptCandidateCenter.x[2] << "\t" << RADIUS << "\t1 0 0\n";
     2711                        *tempstream << "9\n     terminating special property\n";
     2712                        tempstream->close();
     2713                        tempstream->flush();
     2714                        delete(tempstream);
     2715                }
     2716                if (DoTecplotOutput || DoRaster3DOutput)
     2717                        TriangleFilesWritten++;
     2718        }
     2719
     2720        cout << Verbose(1) << "End of Find_next_suitable_triangle\n";
     2721        return true;
     2722};
     2723
     2724/** Tesselates the non convex boundary by rolling a virtual sphere along the surface of the molecule.
     2725 * \param *out output stream for debugging
     2726 * \param *mol molecule structure with Atom's and Bond's
     2727 * \param *Tess Tesselation filled with points, lines and triangles on boundary on return
     2728 * \param *LCList linked cell list of all atoms
     2729 * \param *filename filename prefix for output of vertex data
     2730 * \para RADIUS radius of the virtual sphere
     2731 */
     2732void Find_non_convex_border(ofstream *out, molecule* mol, class Tesselation *Tess, class LinkedCell *LCList, const char *filename, const double RADIUS)
     2733{
     2734        int N = 0;
     2735        bool freeTess = false;
     2736        *out << Verbose(1) << "Entering search for non convex hull. " << endl;
     2737        if (Tess == NULL) {
     2738                *out << Verbose(1) << "Allocating Tesselation struct ..." << endl;
     2739                Tess = new Tesselation;
     2740                freeTess = true;
     2741        }
     2742        bool freeLC = false;
     2743        LineMap::iterator baseline;
     2744        *out << Verbose(0) << "Begin of Find_non_convex_border\n";
     2745        bool flag = false;      // marks whether we went once through all baselines without finding any without two triangles
     2746        bool failflag = false;
     2747
     2748        if (LCList == NULL) {
     2749                LCList = new LinkedCell(mol, 2.*RADIUS);
     2750                freeLC = true;
     2751        }
     2752
     2753        Tess->Find_starting_triangle(out, mol, RADIUS, LCList);
     2754
     2755        baseline = Tess->LinesOnBoundary.begin();
     2756        while ((baseline != Tess->LinesOnBoundary.end()) || (flag)) {
     2757                if (baseline->second->TrianglesCount == 1) {
     2758                        failflag = Tess->Find_next_suitable_triangle(out, mol, *(baseline->second), *(((baseline->second->triangles.begin()))->second), RADIUS, N, filename, LCList); //the line is there, so there is a triangle, but only one.
     2759                        flag = flag || failflag;
     2760                        if (!failflag)
     2761                                cerr << "WARNING: Find_next_suitable_triangle failed." << endl;
     2762                } else {
     2763                        cout << Verbose(1) << "Line " << *baseline->second << " has " << baseline->second->TrianglesCount << " triangles adjacent" << endl;
     2764                }
     2765                N++;
     2766                baseline++;
     2767                if ((baseline == Tess->LinesOnBoundary.end()) && (flag)) {
     2768                        baseline = Tess->LinesOnBoundary.begin();        // restart if we reach end due to newly inserted lines
     2769                        flag = false;
     2770                }
     2771        }
     2772        if (1) { //failflag) {
     2773                *out << Verbose(1) << "Writing final tecplot file\n";
     2774                if (DoTecplotOutput) {
     2775                        string OutputName(filename);
     2776                        OutputName.append(TecplotSuffix);
     2777                        ofstream *tecplot = new ofstream(OutputName.c_str());
     2778                        write_tecplot_file(out, tecplot, Tess, mol, -1);
     2779                        tecplot->close();
     2780                        delete(tecplot);
     2781                }
     2782                if (DoRaster3DOutput) {
     2783                        string OutputName(filename);
     2784                        OutputName.append(Raster3DSuffix);
     2785                        ofstream *raster = new ofstream(OutputName.c_str());
     2786                        write_raster3d_file(out, raster, Tess, mol);
     2787                        raster->close();
     2788                        delete(raster);
     2789                }
     2790        } else {
     2791                cerr << "ERROR: Could definately not find all necessary triangles!" << endl;
     2792        }
     2793        if (freeTess)
     2794                delete(Tess);
     2795        if (freeLC)
     2796                delete(LCList);
     2797        *out << Verbose(0) << "End of Find_non_convex_border\n";
     2798};
     2799
  • src/boundary.hpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    1717
    1818#include <gsl/gsl_poly.h>
     19#include <gsl/gsl_matrix.h>
     20#include <gsl/gsl_linalg.h>
     21#include <gsl/gsl_multimin.h>
     22#include <gsl/gsl_permutation.h>
    1923
     24#include "linkedcell.hpp"
    2025#include "molecules.hpp"
    2126
    2227template <typename T> void SetEndpointsOrdered(T endpoints[2], T endpoint1, T endpoint2)
    2328{
    24   if (endpoint1->Nr < endpoint2->Nr) {
    25     endpoints[0] = endpoint1;
    26     endpoints[1] = endpoint2;
    27   } else {
    28     endpoints[0] = endpoint2;
    29     endpoints[1] = endpoint1;
    30   }
     29        if (endpoint1->Nr < endpoint2->Nr) {
     30                endpoints[0] = endpoint1;
     31                endpoints[1] = endpoint2;
     32        } else {
     33                endpoints[0] = endpoint2;
     34                endpoints[1] = endpoint1;
     35        }
    3136};
    3237
    3338class BoundaryPointSet {
    34   public:
    35     BoundaryPointSet();
    36     BoundaryPointSet(atom *Walker);
    37     ~BoundaryPointSet();
     39        public:
     40                BoundaryPointSet();
     41                BoundaryPointSet(atom *Walker);
     42                ~BoundaryPointSet();
    3843
    39     void AddLine(class BoundaryLineSet *line);
     44                void AddLine(class BoundaryLineSet *line);
    4045
    41     LineMap lines;
    42     int LinesCount;
    43     atom *node;
    44     int Nr;
     46                LineMap lines;
     47                int LinesCount;
     48                atom *node;
     49                int Nr;
    4550};
    4651
    4752class BoundaryLineSet {
    48   public:
    49     BoundaryLineSet();
    50     BoundaryLineSet(class BoundaryPointSet *Point[2], int number);
    51     ~BoundaryLineSet();
     53        public:
     54                BoundaryLineSet();
     55                BoundaryLineSet(class BoundaryPointSet *Point[2], int number);
     56                ~BoundaryLineSet();
    5257
    53     void AddTriangle(class BoundaryTriangleSet *triangle);
     58                void AddTriangle(class BoundaryTriangleSet *triangle);
    5459
    55     class BoundaryPointSet *endpoints[2];
    56     TriangleMap triangles;
    57     int TrianglesCount;
    58     int Nr;
     60                class BoundaryPointSet *endpoints[2];
     61                TriangleMap triangles;
     62                int TrianglesCount;
     63                int Nr;
    5964};
    6065
    6166class BoundaryTriangleSet {
    62   public:
    63     BoundaryTriangleSet();
    64     BoundaryTriangleSet(class BoundaryLineSet *line[3], int number);
    65     ~BoundaryTriangleSet();
     67        public:
     68                BoundaryTriangleSet();
     69                BoundaryTriangleSet(class BoundaryLineSet *line[3], int number);
     70                ~BoundaryTriangleSet();
    6671
    67     void GetNormalVector(Vector &NormalVector);
     72                void GetNormalVector(Vector &NormalVector);
    6873
    69     class BoundaryPointSet *endpoints[3];
    70     class BoundaryLineSet *lines[3];
    71     Vector NormalVector;
    72     int Nr;
     74                class BoundaryPointSet *endpoints[3];
     75                class BoundaryLineSet *lines[3];
     76                Vector NormalVector;
     77                int Nr;
    7378};
    7479
    7580class Tesselation {
    76   public:
     81        public:
    7782
    78     Tesselation();
    79     ~Tesselation();
     83                Tesselation();
     84                ~Tesselation();
    8085
    81     void TesselateOnBoundary(ofstream *out, config *configuration, molecule *mol);
    82     void GuessStartingTriangle(ofstream *out);
    83     void AddPoint(atom * Walker);
    84     void AddTrianglePoint(atom* Candidate, int n);
    85     void AddTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n);
    86     void AddTriangleToLines();
    87     void Find_starting_triangle(molecule* mol, const double RADIUS);
    88     void Find_next_suitable_triangle(ofstream *out, molecule* mol, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, int N, const char *tempbasename);
     86                void TesselateOnBoundary(ofstream *out, config *configuration, molecule *mol);
     87                void GuessStartingTriangle(ofstream *out);
     88                void AddPoint(atom * Walker);
     89                void AddTrianglePoint(atom* Candidate, int n);
     90                void AddTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n);
     91                void AddTriangleToLines();
     92                void Find_starting_triangle(ofstream *out, molecule* mol, const double RADIUS, LinkedCell *LC);
     93                bool Find_next_suitable_triangle(ofstream *out, molecule* mol, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, int N, const char *filename, LinkedCell *LC);
     94                bool CheckPresenceOfTriangle(ofstream *out, atom *Candidates[3]);
     95                void Find_next_suitable_point_via_Angle_of_Sphere(atom* a, atom* b, atom* c, atom* Candidate, atom* Parent, int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint, atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol);
    8996
    90     PointMap PointsOnBoundary;
    91     LineMap LinesOnBoundary;
    92     TriangleMap TrianglesOnBoundary;
    93     class BoundaryPointSet *TPS[3]; //this is a Storage for pointers to triangle points, this and BPS[2] needed due to AddLine restrictions
    94     class BoundaryPointSet *BPS[2];
    95     class BoundaryLineSet *BLS[3];
    96     class BoundaryTriangleSet *BTS;
    97     int PointsOnBoundaryCount;
    98     int LinesOnBoundaryCount;
    99     int TrianglesOnBoundaryCount;
    100     int TriangleFilesWritten;
     97                PointMap PointsOnBoundary;
     98                LineMap LinesOnBoundary;
     99                TriangleMap TrianglesOnBoundary;
     100                class BoundaryPointSet *TPS[3]; //this is a Storage for pointers to triangle points, this and BPS[2] needed due to AddLine restrictions
     101                class BoundaryPointSet *BPS[2];
     102                class BoundaryLineSet *BLS[3];
     103                class BoundaryTriangleSet *BTS;
     104                int PointsOnBoundaryCount;
     105                int LinesOnBoundaryCount;
     106                int TrianglesOnBoundaryCount;
     107                int TriangleFilesWritten;
    101108};
    102109
     
    107114
    108115
    109 double VolumeOfConvexEnvelope(ofstream *out, ofstream *tecplot, config *configuration, Boundaries *BoundaryPoints, molecule *mol);
     116double VolumeOfConvexEnvelope(ofstream *out, const char *filename, config *configuration, Boundaries *BoundaryPoints, molecule *mol);
    110117double * GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, bool IsAngstroem);
    111118void PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol, double ClusterVolume, double celldensity);
    112 void Find_next_suitable_point(atom a, atom b, atom Candidate, int n, Vector *d1, Vector *d2, atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule *mol, bool problem);
    113 void Find_non_convex_border(ofstream *out, const char *filename, molecule* mol);
     119void Find_non_convex_border(ofstream *out, molecule* mol, class Tesselation *T, class LinkedCell *LCList, const char *tempbasename, const double RADIUS);
     120void Find_next_suitable_point(class BoundaryTriangleSet *BaseTriangle, class BoundaryLineSet *BaseLine, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC);
    114121
    115122
  • src/builder.cpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    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 */
     
    5050using namespace std;
    5151
     52#include "boundary.hpp"
     53#include "ellipsoid.hpp"
    5254#include "helpers.hpp"
    5355#include "molecules.hpp"
    54 #include "boundary.hpp"
    5556
    5657/********************************************** Submenu routine **************************************/
     
    6263static void AddAtoms(periodentafel *periode, molecule *mol)
    6364{
    64   atom *first, *second, *third, *fourth;
    65   Vector **atoms;
    66   Vector x,y,z,n;  // coordinates for absolute point in cell volume
    67   double a,b,c;
    68   char choice;  // menu choice char
    69   bool valid;
    70 
    71   cout << Verbose(0) << "===========ADD ATOM============================" << endl;
    72   cout << Verbose(0) << " a - state absolute coordinates of atom" << endl;
    73   cout << Verbose(0) << " b - state relative coordinates of atom wrt to reference point" << endl;
    74   cout << Verbose(0) << " c - state relative coordinates of atom wrt to already placed atom" << endl;
    75   cout << Verbose(0) << " d - state two atoms, two angles and a distance" << endl;
    76   cout << Verbose(0) << " e - least square distance position to a set of atoms" << endl;
    77   cout << Verbose(0) << "all else - go back" << endl;
    78   cout << Verbose(0) << "===============================================" << endl;
    79   cout << Verbose(0) << "Note: Specifiy angles in degrees not multiples of Pi!" << endl;
    80   cout << Verbose(0) << "INPUT: ";
    81   cin >> choice;
    82 
    83   switch (choice) {
    84       case 'a': // absolute coordinates of atom
    85         cout << Verbose(0) << "Enter absolute coordinates." << endl;
    86         first = new atom;
    87         first->x.AskPosition(mol->cell_size, false);
    88         first->type = periode->AskElement();  // give type
    89         mol->AddAtom(first);  // add to molecule
    90         break;
    91 
    92       case 'b': // relative coordinates of atom wrt to reference point
    93         first = new atom;
    94         valid = true;
    95         do {
    96           if (!valid) cout << Verbose(0) << "Resulting position out of cell." << endl;
    97           cout << Verbose(0) << "Enter reference coordinates." << endl;
    98           x.AskPosition(mol->cell_size, true);
    99           cout << Verbose(0) << "Enter relative coordinates." << endl;
    100           first->x.AskPosition(mol->cell_size, false);
    101           first->x.AddVector((const Vector *)&x);
    102           cout << Verbose(0) << "\n";
    103         } while (!(valid = mol->CheckBounds((const Vector *)&first->x)));
    104         first->type = periode->AskElement();  // give type
    105         mol->AddAtom(first);  // add to molecule
    106         break;
    107 
    108       case 'c': // relative coordinates of atom wrt to already placed atom
    109         first = new atom;
    110         valid = true;
    111         do {
    112           if (!valid) cout << Verbose(0) << "Resulting position out of cell." << endl;
    113           second = mol->AskAtom("Enter atom number: ");
    114           cout << Verbose(0) << "Enter relative coordinates." << endl;
    115           first->x.AskPosition(mol->cell_size, false);
    116           for (int i=NDIM;i--;) {
    117             first->x.x[i] += second->x.x[i];
    118           }
    119         } while (!(valid = mol->CheckBounds((const Vector *)&first->x)));
    120         first->type = periode->AskElement();  // give type
    121         mol->AddAtom(first);  // add to molecule
    122         break;
    123 
    124       case 'd': // two atoms, two angles and a distance
    125         first = new atom;
    126         valid = true;
    127         do {
    128           if (!valid) {
    129             cout << Verbose(0) << "Resulting coordinates out of cell - ";
    130             first->x.Output((ofstream *)&cout);
    131             cout << Verbose(0) << endl;
    132           }
    133           cout << Verbose(0) << "First, we need two atoms, the first atom is the central, while the second is the outer one." << endl;
    134           second = mol->AskAtom("Enter central atom: ");
    135           third = mol->AskAtom("Enter second atom (specifying the axis for first angle): ");
    136           fourth = mol->AskAtom("Enter third atom (specifying a plane for second angle): ");
    137           a = ask_value("Enter distance between central (first) and new atom: ");
    138           b = ask_value("Enter angle between new, first and second atom (degrees): ");
    139           b *= M_PI/180.;
    140           bound(&b, 0., 2.*M_PI);
    141           c = ask_value("Enter second angle between new and normal vector of plane defined by first, second and third atom (degrees): ");
    142           c *= M_PI/180.;
    143           bound(&c, -M_PI, M_PI);
    144           cout << Verbose(0) << "radius: " << a << "\t phi: " << b*180./M_PI << "\t theta: " << c*180./M_PI << endl;
     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) {
     85                        case 'a': // absolute coordinates of atom
     86                                cout << Verbose(0) << "Enter absolute coordinates." << endl;
     87                                first = new atom;
     88                                first->x.AskPosition(mol->cell_size, false);
     89                                first->type = periode->AskElement();    // give type
     90                                mol->AddAtom(first);    // add to molecule
     91                                break;
     92
     93                        case 'b': // relative coordinates of atom wrt to reference point
     94                                first = new atom;
     95                                valid = true;
     96                                do {
     97                                        if (!valid) cout << Verbose(0) << "Resulting position out of cell." << endl;
     98                                        cout << Verbose(0) << "Enter reference coordinates." << endl;
     99                                        x.AskPosition(mol->cell_size, true);
     100                                        cout << Verbose(0) << "Enter relative coordinates." << endl;
     101                                        first->x.AskPosition(mol->cell_size, false);
     102                                        first->x.AddVector((const Vector *)&x);
     103                                        cout << Verbose(0) << "\n";
     104                                } while (!(valid = mol->CheckBounds((const Vector *)&first->x)));
     105                                first->type = periode->AskElement();    // give type
     106                                mol->AddAtom(first);    // add to molecule
     107                                break;
     108
     109                        case 'c': // relative coordinates of atom wrt to already placed atom
     110                                first = new atom;
     111                                valid = true;
     112                                do {
     113                                        if (!valid) cout << Verbose(0) << "Resulting position out of cell." << endl;
     114                                        second = mol->AskAtom("Enter atom number: ");
     115                                        cout << Verbose(0) << "Enter relative coordinates." << endl;
     116                                        first->x.AskPosition(mol->cell_size, false);
     117                                        for (int i=NDIM;i--;) {
     118                                                first->x.x[i] += second->x.x[i];
     119                                        }
     120                                } while (!(valid = mol->CheckBounds((const Vector *)&first->x)));
     121                                first->type = periode->AskElement();    // give type
     122                                mol->AddAtom(first);    // add to molecule
     123                                break;
     124
     125                        case 'd': // two atoms, two angles and a distance
     126                                first = new atom;
     127                                valid = true;
     128                                do {
     129                                        if (!valid) {
     130                                                cout << Verbose(0) << "Resulting coordinates out of cell - ";
     131                                                first->x.Output((ofstream *)&cout);
     132                                                cout << Verbose(0) << endl;
     133                                        }
     134                                        cout << Verbose(0) << "First, we need two atoms, the first atom is the central, while the second is the outer one." << endl;
     135                                        second = mol->AskAtom("Enter central atom: ");
     136                                        third = mol->AskAtom("Enter second atom (specifying the axis for first angle): ");
     137                                        fourth = mol->AskAtom("Enter third atom (specifying a plane for second angle): ");
     138                                        a = ask_value("Enter distance between central (first) and new atom: ");
     139                                        b = ask_value("Enter angle between new, first and second atom (degrees): ");
     140                                        b *= M_PI/180.;
     141                                        bound(&b, 0., 2.*M_PI);
     142                                        c = ask_value("Enter second angle between new and normal vector of plane defined by first, second and third atom (degrees): ");
     143                                        c *= M_PI/180.;
     144                                        bound(&c, -M_PI, M_PI);
     145                                        cout << Verbose(0) << "radius: " << a << "\t phi: " << b*180./M_PI << "\t theta: " << c*180./M_PI << endl;
    145146/*
    146           second->Output(1,1,(ofstream *)&cout);
    147           third->Output(1,2,(ofstream *)&cout);
    148           fourth->Output(1,3,(ofstream *)&cout);
    149           n.MakeNormalvector((const vector *)&second->x, (const vector *)&third->x, (const vector *)&fourth->x);
    150           x.Copyvector(&second->x);
    151           x.SubtractVector(&third->x);
    152           x.Copyvector(&fourth->x);
    153           x.SubtractVector(&third->x);
    154 
    155           if (!z.SolveSystem(&x,&y,&n, b, c, a)) {
    156             cout << Verbose(0) << "Failure solving self-dependent linear system!" << endl;
    157             continue;
    158           }
    159           cout << Verbose(0) << "resulting relative coordinates: ";
    160           z.Output((ofstream *)&cout);
    161           cout << Verbose(0) << endl;
    162           */
    163           // calc axis vector
    164           x.CopyVector(&second->x);
    165           x.SubtractVector(&third->x);
    166           x.Normalize();
    167           cout << "x: ",
    168           x.Output((ofstream *)&cout);
    169           cout << endl;
    170           z.MakeNormalVector(&second->x,&third->x,&fourth->x);
    171           cout << "z: ",
    172           z.Output((ofstream *)&cout);
    173           cout << endl;
    174           y.MakeNormalVector(&x,&z);
    175           cout << "y: ",
    176           y.Output((ofstream *)&cout);
    177           cout << endl;
    178 
    179           // rotate vector around first angle
    180           first->x.CopyVector(&x);
    181           first->x.RotateVector(&z,b - M_PI);
    182           cout << "Rotated vector: ",
    183           first->x.Output((ofstream *)&cout);
    184           cout << endl;
    185           // remove the projection onto the rotation plane of the second angle
    186           n.CopyVector(&y);
    187           n.Scale(first->x.Projection(&y));
    188           cout << "N1: ",
    189           n.Output((ofstream *)&cout);
    190           cout << endl;
    191           first->x.SubtractVector(&n);
    192           cout << "Subtracted vector: ",
    193           first->x.Output((ofstream *)&cout);
    194           cout << endl;
    195           n.CopyVector(&z);
    196           n.Scale(first->x.Projection(&z));
    197           cout << "N2: ",
    198           n.Output((ofstream *)&cout);
    199           cout << endl;
    200           first->x.SubtractVector(&n);
    201           cout << "2nd subtracted vector: ",
    202           first->x.Output((ofstream *)&cout);
    203           cout << endl;
    204 
    205           // rotate another vector around second angle
    206           n.CopyVector(&y);
    207           n.RotateVector(&x,c - M_PI);
    208           cout << "2nd Rotated vector: ",
    209           n.Output((ofstream *)&cout);
    210           cout << endl;
    211 
    212           // add the two linear independent vectors
    213           first->x.AddVector(&n);
    214           first->x.Normalize();
    215           first->x.Scale(a);
    216           first->x.AddVector(&second->x);
    217 
    218           cout << Verbose(0) << "resulting coordinates: ";
    219           first->x.Output((ofstream *)&cout);
    220           cout << Verbose(0) << endl;
    221         } while (!(valid = mol->CheckBounds((const Vector *)&first->x)));
    222         first->type = periode->AskElement();  // give type
    223         mol->AddAtom(first);  // add to molecule
    224         break;
    225 
    226       case 'e': // least square distance position to a set of atoms
    227         first = new atom;
    228         atoms = new (Vector*[128]);
    229         valid = true;
    230         for(int i=128;i--;)
    231           atoms[i] = NULL;
    232         int i=0, j=0;
    233         cout << Verbose(0) << "Now we need at least three molecules.\n";
    234         do {
    235           cout << Verbose(0) << "Enter " << i+1 << "th atom: ";
    236           cin >> j;
    237           if (j != -1) {
    238             second = mol->FindAtom(j);
    239             atoms[i++] = &(second->x);
    240           }
    241         } while ((j != -1) && (i<128));
    242         if (i >= 2) {
    243           first->x.LSQdistance(atoms, i);
    244 
    245           first->x.Output((ofstream *)&cout);
    246           first->type = periode->AskElement();  // give type
    247           mol->AddAtom(first);  // add to molecule
    248         } else {
    249           delete first;
    250           cout << Verbose(0) << "Please enter at least two vectors!\n";
    251         }
    252         break;
    253   };
     147                                        second->Output(1,1,(ofstream *)&cout);
     148                                        third->Output(1,2,(ofstream *)&cout);
     149                                        fourth->Output(1,3,(ofstream *)&cout);
     150                                        n.MakeNormalvector((const vector *)&second->x, (const vector *)&third->x, (const vector *)&fourth->x);
     151                                        x.Copyvector(&second->x);
     152                                        x.SubtractVector(&third->x);
     153                                        x.Copyvector(&fourth->x);
     154                                        x.SubtractVector(&third->x);
     155
     156                                        if (!z.SolveSystem(&x,&y,&n, b, c, a)) {
     157                                                cout << Verbose(0) << "Failure solving self-dependent linear system!" << endl;
     158                                                continue;
     159                                        }
     160                                        cout << Verbose(0) << "resulting relative coordinates: ";
     161                                        z.Output((ofstream *)&cout);
     162                                        cout << Verbose(0) << endl;
     163                                        */
     164                                        // calc axis vector
     165                                        x.CopyVector(&second->x);
     166                                        x.SubtractVector(&third->x);
     167                                        x.Normalize();
     168                                        cout << "x: ",
     169                                        x.Output((ofstream *)&cout);
     170                                        cout << endl;
     171                                        z.MakeNormalVector(&second->x,&third->x,&fourth->x);
     172                                        cout << "z: ",
     173                                        z.Output((ofstream *)&cout);
     174                                        cout << endl;
     175                                        y.MakeNormalVector(&x,&z);
     176                                        cout << "y: ",
     177                                        y.Output((ofstream *)&cout);
     178                                        cout << endl;
     179
     180                                        // rotate vector around first angle
     181                                        first->x.CopyVector(&x);
     182                                        first->x.RotateVector(&z,b - M_PI);
     183                                        cout << "Rotated vector: ",
     184                                        first->x.Output((ofstream *)&cout);
     185                                        cout << endl;
     186                                        // remove the projection onto the rotation plane of the second angle
     187                                        n.CopyVector(&y);
     188                                        n.Scale(first->x.Projection(&y));
     189                                        cout << "N1: ",
     190                                        n.Output((ofstream *)&cout);
     191                                        cout << endl;
     192                                        first->x.SubtractVector(&n);
     193                                        cout << "Subtracted vector: ",
     194                                        first->x.Output((ofstream *)&cout);
     195                                        cout << endl;
     196                                        n.CopyVector(&z);
     197                                        n.Scale(first->x.Projection(&z));
     198                                        cout << "N2: ",
     199                                        n.Output((ofstream *)&cout);
     200                                        cout << endl;
     201                                        first->x.SubtractVector(&n);
     202                                        cout << "2nd subtracted vector: ",
     203                                        first->x.Output((ofstream *)&cout);
     204                                        cout << endl;
     205
     206                                        // rotate another vector around second angle
     207                                        n.CopyVector(&y);
     208                                        n.RotateVector(&x,c - M_PI);
     209                                        cout << "2nd Rotated vector: ",
     210                                        n.Output((ofstream *)&cout);
     211                                        cout << endl;
     212
     213                                        // add the two linear independent vectors
     214                                        first->x.AddVector(&n);
     215                                        first->x.Normalize();
     216                                        first->x.Scale(a);
     217                                        first->x.AddVector(&second->x);
     218
     219                                        cout << Verbose(0) << "resulting coordinates: ";
     220                                        first->x.Output((ofstream *)&cout);
     221                                        cout << Verbose(0) << endl;
     222                                } while (!(valid = mol->CheckBounds((const Vector *)&first->x)));
     223                                first->type = periode->AskElement();    // give type
     224                                mol->AddAtom(first);    // add to molecule
     225                                break;
     226
     227                        case 'e': // least square distance position to a set of atoms
     228                                first = new atom;
     229                                atoms = new (Vector*[128]);
     230                                valid = true;
     231                                for(int i=128;i--;)
     232                                        atoms[i] = NULL;
     233                                int i=0, j=0;
     234                                cout << Verbose(0) << "Now we need at least three molecules.\n";
     235                                do {
     236                                        cout << Verbose(0) << "Enter " << i+1 << "th atom: ";
     237                                        cin >> j;
     238                                        if (j != -1) {
     239                                                second = mol->FindAtom(j);
     240                                                atoms[i++] = &(second->x);
     241                                        }
     242                                } while ((j != -1) && (i<128));
     243                                if (i >= 2) {
     244                                        first->x.LSQdistance(atoms, i);
     245
     246                                        first->x.Output((ofstream *)&cout);
     247                                        first->type = periode->AskElement();    // give type
     248                                        mol->AddAtom(first);    // add to molecule
     249                                } else {
     250                                        delete first;
     251                                        cout << Verbose(0) << "Please enter at least two vectors!\n";
     252                                }
     253                                break;
     254        };
    254255};
    255256
     
    259260static void CenterAtoms(molecule *mol)
    260261{
    261   Vector x, y;
    262   char choice;  // menu choice char
    263 
    264   cout << Verbose(0) << "===========CENTER ATOMS=========================" << endl;
    265   cout << Verbose(0) << " a - on origin" << endl;
    266   cout << Verbose(0) << " b - on center of gravity" << endl;
    267   cout << Verbose(0) << " c - within box with additional boundary" << endl;
    268   cout << Verbose(0) << " d - within given simulation box" << endl;
    269   cout << Verbose(0) << "all else - go back" << endl;
    270   cout << Verbose(0) << "===============================================" << endl;
    271   cout << Verbose(0) << "INPUT: ";
    272   cin >> choice;
    273 
    274   switch (choice) {
    275     default:
    276       cout << Verbose(0) << "Not a valid choice." << endl;
    277       break;
    278     case 'a':
    279       cout << Verbose(0) << "Centering atoms in config file on origin." << endl;
    280       mol->CenterOrigin((ofstream *)&cout, &x);
    281       break;
    282     case 'b':
    283       cout << Verbose(0) << "Centering atoms in config file on center of gravity." << endl;
    284       mol->CenterGravity((ofstream *)&cout, &x);
    285       break;
    286     case 'c':
    287       cout << Verbose(0) << "Centering atoms in config file within given additional boundary." << endl;
    288       for (int i=0;i<NDIM;i++) {
    289         cout << Verbose(0) << "Enter axis " << i << " boundary: ";
    290         cin >> y.x[i];
    291       }
    292       mol->CenterEdge((ofstream *)&cout, &x);  // make every coordinate positive
    293       mol->Translate(&y); // translate by boundary
    294       mol->SetBoxDimension(&(x+y*2));  // update Box of atoms by boundary
    295       break;
    296     case 'd':
    297       cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl;
    298       for (int i=0;i<NDIM;i++) {
    299         cout << Verbose(0) << "Enter axis " << i << " boundary: ";
    300         cin >> x.x[i];
    301       }
    302       // center
    303       mol->CenterInBox((ofstream *)&cout, &x);
    304       // update Box of atoms by boundary
    305       mol->SetBoxDimension(&x);
    306       break;
    307   }
     262        Vector x, y, helper;
     263        char choice;    // menu choice char
     264
     265        cout << Verbose(0) << "===========CENTER ATOMS=========================" << endl;
     266        cout << Verbose(0) << " a - on origin" << endl;
     267        cout << Verbose(0) << " b - on center of gravity" << endl;
     268        cout << Verbose(0) << " c - within box with additional boundary" << endl;
     269        cout << Verbose(0) << " d - within given simulation box" << endl;
     270        cout << Verbose(0) << "all else - go back" << endl;
     271        cout << Verbose(0) << "===============================================" << endl;
     272        cout << Verbose(0) << "INPUT: ";
     273        cin >> choice;
     274
     275        switch (choice) {
     276                default:
     277                        cout << Verbose(0) << "Not a valid choice." << endl;
     278                        break;
     279                case 'a':
     280                        cout << Verbose(0) << "Centering atoms in config file on origin." << endl;
     281                        mol->CenterOrigin((ofstream *)&cout, &x);
     282                        break;
     283                case 'b':
     284                        cout << Verbose(0) << "Centering atoms in config file on center of gravity." << endl;
     285                        mol->CenterGravity((ofstream *)&cout, &x);
     286                        break;
     287                case 'c':
     288                        cout << Verbose(0) << "Centering atoms in config file within given additional boundary." << endl;
     289                        for (int i=0;i<NDIM;i++) {
     290                                cout << Verbose(0) << "Enter axis " << i << " boundary: ";
     291                                cin >> y.x[i];
     292                        }
     293                        mol->CenterEdge((ofstream *)&cout, &x); // make every coordinate positive
     294                        mol->Translate(&y); // translate by boundary
     295                        helper.CopyVector(&y);
     296                        helper.Scale(2.);
     297                        helper.AddVector(&x);
     298                        mol->SetBoxDimension(&helper);  // update Box of atoms by boundary
     299                        break;
     300                case 'd':
     301                        cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl;
     302                        for (int i=0;i<NDIM;i++) {
     303                                cout << Verbose(0) << "Enter axis " << i << " boundary: ";
     304                                cin >> x.x[i];
     305                        }
     306                        // center
     307                        mol->CenterInBox((ofstream *)&cout, &x);
     308                        // update Box of atoms by boundary
     309                        mol->SetBoxDimension(&x);
     310                        break;
     311        }
    308312};
    309313
     
    314318static void AlignAtoms(periodentafel *periode, molecule *mol)
    315319{
    316   atom *first, *second, *third;
    317   Vector x,n;
    318   char choice;  // menu choice char
    319 
    320   cout << Verbose(0) << "===========ALIGN ATOMS=========================" << endl;
    321   cout << Verbose(0) << " a - state three atoms defining align plane" << endl;
    322   cout << Verbose(0) << " b - state alignment vector" << endl;
    323   cout << Verbose(0) << " c - state two atoms in alignment direction" << endl;
    324   cout << Verbose(0) << " d - align automatically by least square fit" << endl;
    325   cout << Verbose(0) << "all else - go back" << endl;
    326   cout << Verbose(0) << "===============================================" << endl;
    327   cout << Verbose(0) << "INPUT: ";
    328   cin >> choice;
    329 
    330   switch (choice) {
    331     default:
    332     case 'a': // three atoms defining mirror plane
    333       first = mol->AskAtom("Enter first atom: ");
    334       second = mol->AskAtom("Enter second atom: ");
    335       third = mol->AskAtom("Enter third atom: ");
    336 
    337       n.MakeNormalVector((const Vector *)&first->x,(const Vector *)&second->x,(const Vector *)&third->x);
    338       break;
    339     case 'b': // normal vector of mirror plane
    340       cout << Verbose(0) << "Enter normal vector of mirror plane." << endl;
    341       n.AskPosition(mol->cell_size,0);
    342       n.Normalize();
    343       break;
    344     case 'c': // three atoms defining mirror plane
    345       first = mol->AskAtom("Enter first atom: ");
    346       second = mol->AskAtom("Enter second atom: ");
    347 
    348       n.CopyVector((const Vector *)&first->x);
    349       n.SubtractVector((const Vector *)&second->x);
    350       n.Normalize();
    351       break;
    352     case 'd':
    353       char shorthand[4];
    354       Vector a;
    355       struct lsq_params param;
    356       do {
    357         fprintf(stdout, "Enter the element of atoms to be chosen: ");
    358         fscanf(stdin, "%3s", shorthand);
    359       } while ((param.type = periode->FindElement(shorthand)) == NULL);
    360       cout << Verbose(0) << "Element is " << param.type->name << endl;
    361       mol->GetAlignvector(&param);
    362       for (int i=NDIM;i--;) {
    363         x.x[i] = gsl_vector_get(param.x,i);
    364         n.x[i] = gsl_vector_get(param.x,i+NDIM);
    365       }
    366       gsl_vector_free(param.x);
    367       cout << Verbose(0) << "Offset vector: ";
    368       x.Output((ofstream *)&cout);
    369       cout << Verbose(0) << endl;
    370       n.Normalize();
    371       break;
    372   };
    373   cout << Verbose(0) << "Alignment vector: ";
    374   n.Output((ofstream *)&cout);
    375   cout << Verbose(0) << endl;
    376   mol->Align(&n);
     320        atom *first, *second, *third;
     321        Vector x,n;
     322        char choice;    // menu choice char
     323
     324        cout << Verbose(0) << "===========ALIGN ATOMS=========================" << endl;
     325        cout << Verbose(0) << " a - state three atoms defining align plane" << endl;
     326        cout << Verbose(0) << " b - state alignment vector" << endl;
     327        cout << Verbose(0) << " c - state two atoms in alignment direction" << endl;
     328        cout << Verbose(0) << " d - align automatically by least square fit" << endl;
     329        cout << Verbose(0) << "all else - go back" << endl;
     330        cout << Verbose(0) << "===============================================" << endl;
     331        cout << Verbose(0) << "INPUT: ";
     332        cin >> choice;
     333
     334        switch (choice) {
     335                default:
     336                case 'a': // three atoms defining mirror plane
     337                        first = mol->AskAtom("Enter first atom: ");
     338                        second = mol->AskAtom("Enter second atom: ");
     339                        third = mol->AskAtom("Enter third atom: ");
     340
     341                        n.MakeNormalVector((const Vector *)&first->x,(const Vector *)&second->x,(const Vector *)&third->x);
     342                        break;
     343                case 'b': // normal vector of mirror plane
     344                        cout << Verbose(0) << "Enter normal vector of mirror plane." << endl;
     345                        n.AskPosition(mol->cell_size,0);
     346                        n.Normalize();
     347                        break;
     348                case 'c': // three atoms defining mirror plane
     349                        first = mol->AskAtom("Enter first atom: ");
     350                        second = mol->AskAtom("Enter second atom: ");
     351
     352                        n.CopyVector((const Vector *)&first->x);
     353                        n.SubtractVector((const Vector *)&second->x);
     354                        n.Normalize();
     355                        break;
     356                case 'd':
     357                        char shorthand[4];
     358                        Vector a;
     359                        struct lsq_params param;
     360                        do {
     361                                fprintf(stdout, "Enter the element of atoms to be chosen: ");
     362                                fscanf(stdin, "%3s", shorthand);
     363                        } while ((param.type = periode->FindElement(shorthand)) == NULL);
     364                        cout << Verbose(0) << "Element is " << param.type->name << endl;
     365                        mol->GetAlignvector(&param);
     366                        for (int i=NDIM;i--;) {
     367                                x.x[i] = gsl_vector_get(param.x,i);
     368                                n.x[i] = gsl_vector_get(param.x,i+NDIM);
     369                        }
     370                        gsl_vector_free(param.x);
     371                        cout << Verbose(0) << "Offset vector: ";
     372                        x.Output((ofstream *)&cout);
     373                        cout << Verbose(0) << endl;
     374                        n.Normalize();
     375                        break;
     376        };
     377        cout << Verbose(0) << "Alignment vector: ";
     378        n.Output((ofstream *)&cout);
     379        cout << Verbose(0) << endl;
     380        mol->Align(&n);
    377381};
    378382
     
    382386static void MirrorAtoms(molecule *mol)
    383387{
    384   atom *first, *second, *third;
    385   Vector n;
    386   char choice;  // menu choice char
    387 
    388   cout << Verbose(0) << "===========MIRROR ATOMS=========================" << endl;
    389   cout << Verbose(0) << " a - state three atoms defining mirror plane" << endl;
    390   cout << Verbose(0) << " b - state normal vector of mirror plane" << endl;
    391   cout << Verbose(0) << " c - state two atoms in normal direction" << endl;
    392   cout << Verbose(0) << "all else - go back" << endl;
    393   cout << Verbose(0) << "===============================================" << endl;
    394   cout << Verbose(0) << "INPUT: ";
    395   cin >> choice;
    396 
    397   switch (choice) {
    398     default:
    399     case 'a': // three atoms defining mirror plane
    400       first = mol->AskAtom("Enter first atom: ");
    401       second = mol->AskAtom("Enter second atom: ");
    402       third = mol->AskAtom("Enter third atom: ");
    403 
    404       n.MakeNormalVector((const Vector *)&first->x,(const Vector *)&second->x,(const Vector *)&third->x);
    405       break;
    406     case 'b': // normal vector of mirror plane
    407       cout << Verbose(0) << "Enter normal vector of mirror plane." << endl;
    408       n.AskPosition(mol->cell_size,0);
    409       n.Normalize();
    410       break;
    411     case 'c': // three atoms defining mirror plane
    412       first = mol->AskAtom("Enter first atom: ");
    413       second = mol->AskAtom("Enter second atom: ");
    414 
    415       n.CopyVector((const Vector *)&first->x);
    416       n.SubtractVector((const Vector *)&second->x);
    417       n.Normalize();
    418       break;
    419   };
    420   cout << Verbose(0) << "Normal vector: ";
    421   n.Output((ofstream *)&cout);
    422   cout << Verbose(0) << endl;
    423   mol->Mirror((const Vector *)&n);
     388        atom *first, *second, *third;
     389        Vector n;
     390        char choice;    // menu choice char
     391
     392        cout << Verbose(0) << "===========MIRROR ATOMS=========================" << endl;
     393        cout << Verbose(0) << " a - state three atoms defining mirror plane" << endl;
     394        cout << Verbose(0) << " b - state normal vector of mirror plane" << endl;
     395        cout << Verbose(0) << " c - state two atoms in normal direction" << endl;
     396        cout << Verbose(0) << "all else - go back" << endl;
     397        cout << Verbose(0) << "===============================================" << endl;
     398        cout << Verbose(0) << "INPUT: ";
     399        cin >> choice;
     400
     401        switch (choice) {
     402                default:
     403                case 'a': // three atoms defining mirror plane
     404                        first = mol->AskAtom("Enter first atom: ");
     405                        second = mol->AskAtom("Enter second atom: ");
     406                        third = mol->AskAtom("Enter third atom: ");
     407
     408                        n.MakeNormalVector((const Vector *)&first->x,(const Vector *)&second->x,(const Vector *)&third->x);
     409                        break;
     410                case 'b': // normal vector of mirror plane
     411                        cout << Verbose(0) << "Enter normal vector of mirror plane." << endl;
     412                        n.AskPosition(mol->cell_size,0);
     413                        n.Normalize();
     414                        break;
     415                case 'c': // three atoms defining mirror plane
     416                        first = mol->AskAtom("Enter first atom: ");
     417                        second = mol->AskAtom("Enter second atom: ");
     418
     419                        n.CopyVector((const Vector *)&first->x);
     420                        n.SubtractVector((const Vector *)&second->x);
     421                        n.Normalize();
     422                        break;
     423        };
     424        cout << Verbose(0) << "Normal vector: ";
     425        n.Output((ofstream *)&cout);
     426        cout << Verbose(0) << endl;
     427        mol->Mirror((const Vector *)&n);
    424428};
    425429
     
    429433static void RemoveAtoms(molecule *mol)
    430434{
    431   atom *first, *second;
    432   int axis;
    433   double tmp1, tmp2;
    434   char choice;  // menu choice char
    435 
    436   cout << Verbose(0) << "===========REMOVE ATOMS=========================" << endl;
    437   cout << Verbose(0) << " a - state atom for removal by number" << endl;
    438   cout << Verbose(0) << " b - keep only in radius around atom" << endl;
    439   cout << Verbose(0) << " c - remove this with one axis greater value" << endl;
    440   cout << Verbose(0) << "all else - go back" << endl;
    441   cout << Verbose(0) << "===============================================" << endl;
    442   cout << Verbose(0) << "INPUT: ";
    443   cin >> choice;
    444 
    445   switch (choice) {
    446     default:
    447     case 'a':
    448       if (mol->RemoveAtom(mol->AskAtom("Enter number of atom within molecule: ")))
    449         cout << Verbose(1) << "Atom removed." << endl;
    450       else
    451         cout << Verbose(1) << "Atom not found." << endl;
    452       break;
    453     case 'b':
    454       second = mol->AskAtom("Enter number of atom as reference point: ");
    455       cout << Verbose(0) << "Enter radius: ";
    456       cin >> tmp1;
    457       first = mol->start;
    458       while(first->next != mol->end) {
    459         first = first->next;
    460         if (first->x.Distance((const Vector *)&second->x) > tmp1*tmp1) // distance to first above radius ...
    461           mol->RemoveAtom(first);
    462       }
    463       break;
    464     case 'c':
    465       cout << Verbose(0) << "Which axis is it: ";
    466       cin >> axis;
    467       cout << Verbose(0) << "Left inward boundary: ";
    468       cin >> tmp1;
    469       cout << Verbose(0) << "Right inward boundary: ";
    470       cin >> tmp2;
    471       first = mol->start;
    472       while(first->next != mol->end) {
    473         first = first->next;
    474         if ((first->x.x[axis] > tmp2) || (first->x.x[axis] < tmp1)) // out of boundary ...
    475           mol->RemoveAtom(first);
    476       }
    477       break;
    478   };
    479   //mol->Output((ofstream *)&cout);
    480   choice = 'r';
     435        atom *first, *second;
     436        int axis;
     437        double tmp1, tmp2;
     438        char choice;    // menu choice char
     439
     440        cout << Verbose(0) << "===========REMOVE ATOMS=========================" << endl;
     441        cout << Verbose(0) << " a - state atom for removal by number" << endl;
     442        cout << Verbose(0) << " b - keep only in radius around atom" << endl;
     443        cout << Verbose(0) << " c - remove this with one axis greater value" << endl;
     444        cout << Verbose(0) << "all else - go back" << endl;
     445        cout << Verbose(0) << "===============================================" << endl;
     446        cout << Verbose(0) << "INPUT: ";
     447        cin >> choice;
     448
     449        switch (choice) {
     450                default:
     451                case 'a':
     452                        if (mol->RemoveAtom(mol->AskAtom("Enter number of atom within molecule: ")))
     453                                cout << Verbose(1) << "Atom removed." << endl;
     454                        else
     455                                cout << Verbose(1) << "Atom not found." << endl;
     456                        break;
     457                case 'b':
     458                        second = mol->AskAtom("Enter number of atom as reference point: ");
     459                        cout << Verbose(0) << "Enter radius: ";
     460                        cin >> tmp1;
     461                        first = mol->start;
     462                        while(first->next != mol->end) {
     463                                first = first->next;
     464                                if (first->x.DistanceSquared((const Vector *)&second->x) > tmp1*tmp1) // distance to first above radius ...
     465                                        mol->RemoveAtom(first);
     466                        }
     467                        break;
     468                case 'c':
     469                        cout << Verbose(0) << "Which axis is it: ";
     470                        cin >> axis;
     471                        cout << Verbose(0) << "Left inward boundary: ";
     472                        cin >> tmp1;
     473                        cout << Verbose(0) << "Right inward boundary: ";
     474                        cin >> tmp2;
     475                        first = mol->start;
     476                        while(first->next != mol->end) {
     477                                first = first->next;
     478                                if ((first->x.x[axis] > tmp2) || (first->x.x[axis] < tmp1)) // out of boundary ...
     479                                        mol->RemoveAtom(first);
     480                        }
     481                        break;
     482        };
     483        //mol->Output((ofstream *)&cout);
     484        choice = 'r';
    481485};
    482486
     
    487491static void MeasureAtoms(periodentafel *periode, molecule *mol, config *configuration)
    488492{
    489   atom *first, *second, *third;
    490   Vector x,y;
    491   double min[256], tmp1, tmp2, tmp3;
    492   int Z;
    493   char choice;  // menu choice char
    494 
    495   cout << Verbose(0) << "===========MEASURE ATOMS=========================" << endl;
    496   cout << Verbose(0) << " a - calculate bond length between one atom and all others" << endl;
    497   cout << Verbose(0) << " b - calculate bond length between two atoms" << endl;
    498   cout << Verbose(0) << " c - calculate bond angle" << endl;
    499   cout << Verbose(0) << " d - calculate principal axis of the system" << endl;
    500   cout << Verbose(0) << " e - calculate volume of the convex envelope" << endl;
    501   cout << Verbose(0) << " f - calculate temperature from current velocity" << endl;
    502   cout << Verbose(0) << " g - output all temperatures per step from velocities" << endl;
    503   cout << Verbose(0) << "all else - go back" << endl;
    504   cout << Verbose(0) << "===============================================" << endl;
    505   cout << Verbose(0) << "INPUT: ";
    506   cin >> choice;
    507 
    508   switch(choice) {
    509     default:
    510       cout << Verbose(1) << "Not a valid choice." << endl;
    511       break;
    512     case 'a':
    513       first = mol->AskAtom("Enter first atom: ");
    514       for (int i=MAX_ELEMENTS;i--;)
    515         min[i] = 0.;
    516 
    517       second = mol->start;
    518       while ((second->next != mol->end)) {
    519         second = second->next; // advance
    520         Z = second->type->Z;
    521         tmp1 = 0.;
    522         if (first != second) {
    523           x.CopyVector((const Vector *)&first->x);
    524           x.SubtractVector((const Vector *)&second->x);
    525           tmp1 = x.Norm();
    526         }
    527         if ((tmp1 != 0.) && ((min[Z] == 0.) || (tmp1 < min[Z]))) min[Z] = tmp1;
    528         //cout << Verbose(0) << "Bond length between Atom " << first->nr << " and " << second->nr << ": " << tmp1 << " a.u." << endl;
    529       }
    530       for (int i=MAX_ELEMENTS;i--;)
    531         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;
    532       break;
    533 
    534     case 'b':
    535       first = mol->AskAtom("Enter first atom: ");
    536       second = mol->AskAtom("Enter second atom: ");
    537       for (int i=NDIM;i--;)
    538         min[i] = 0.;
    539       x.CopyVector((const Vector *)&first->x);
    540       x.SubtractVector((const Vector *)&second->x);
    541       tmp1 = x.Norm();
    542       cout << Verbose(1) << "Distance vector is ";
    543       x.Output((ofstream *)&cout);
    544       cout << "." << endl << "Norm of distance is " << tmp1 << "." << endl;
    545       break;
    546 
    547     case 'c':
    548       cout << Verbose(0) << "Evaluating bond angle between three - first, central, last - atoms." << endl;
    549       first = mol->AskAtom("Enter first atom: ");
    550       second = mol->AskAtom("Enter central atom: ");
    551       third  = mol->AskAtom("Enter last atom: ");
    552       tmp1 = tmp2 = tmp3 = 0.;
    553       x.CopyVector((const Vector *)&first->x);
    554       x.SubtractVector((const Vector *)&second->x);
    555       y.CopyVector((const Vector *)&third->x);
    556       y.SubtractVector((const Vector *)&second->x);
    557       cout << Verbose(0) << "Bond angle between first atom Nr." << first->nr << ", central atom Nr." << second->nr << " and last atom Nr." << third->nr << ": ";
    558       cout << Verbose(0) << (acos(x.ScalarProduct((const Vector *)&y)/(y.Norm()*x.Norm()))/M_PI*180.) << " degrees" << endl;
    559       break;
    560     case 'd':
    561         cout << Verbose(0) << "Evaluating prinicipal axis." << endl;
    562         cout << Verbose(0) << "Shall we rotate? [0/1]: ";
    563         cin >> Z;
    564         if ((Z >=0) && (Z <=1))
    565           mol->PrincipalAxisSystem((ofstream *)&cout, (bool)Z);
    566         else
    567           mol->PrincipalAxisSystem((ofstream *)&cout, false);
    568         break;
    569     case 'e':
    570         cout << Verbose(0) << "Evaluating volume of the convex envelope.";
    571         VolumeOfConvexEnvelope((ofstream *)&cout, NULL, configuration, NULL, mol);
    572         break;
    573     case 'f':
    574       mol->OutputTemperatureFromTrajectories((ofstream *)&cout, mol->MDSteps-1, mol->MDSteps, (ofstream *)&cout);
    575       break;
    576     case 'g':
    577       {
    578         char filename[255];
    579         cout << "Please enter filename: " << endl;
    580         cin >> filename;
    581         cout << Verbose(1) << "Storing temperatures in " << filename << "." << endl;
    582         ofstream *output = new ofstream(filename, ios::trunc);
    583         if (!mol->OutputTemperatureFromTrajectories((ofstream *)&cout, 0, mol->MDSteps, output))
    584           cout << Verbose(2) << "File could not be written." << endl;
    585         else
    586           cout << Verbose(2) << "File stored." << endl;
    587         output->close();
    588         delete(output);
    589       }
    590       break;
    591   }
     493        atom *first, *second, *third;
     494        Vector x,y;
     495        double min[256], tmp1, tmp2, tmp3;
     496        int Z;
     497        char choice;    // menu choice char
     498
     499        cout << Verbose(0) << "===========MEASURE ATOMS=========================" << endl;
     500        cout << Verbose(0) << " a - calculate bond length between one atom and all others" << endl;
     501        cout << Verbose(0) << " b - calculate bond length between two atoms" << endl;
     502        cout << Verbose(0) << " c - calculate bond angle" << endl;
     503        cout << Verbose(0) << " d - calculate principal axis of the system" << endl;
     504        cout << Verbose(0) << " e - calculate volume of the convex envelope" << endl;
     505        cout << Verbose(0) << " f - calculate temperature from current velocity" << endl;
     506        cout << Verbose(0) << " g - output all temperatures per step from velocities" << endl;
     507        cout << Verbose(0) << "all else - go back" << endl;
     508        cout << Verbose(0) << "===============================================" << endl;
     509        cout << Verbose(0) << "INPUT: ";
     510        cin >> choice;
     511
     512        switch(choice) {
     513                default:
     514                        cout << Verbose(1) << "Not a valid choice." << endl;
     515                        break;
     516                case 'a':
     517                        first = mol->AskAtom("Enter first atom: ");
     518                        for (int i=MAX_ELEMENTS;i--;)
     519                                min[i] = 0.;
     520
     521                        second = mol->start;
     522                        while ((second->next != mol->end)) {
     523                                second = second->next; // advance
     524                                Z = second->type->Z;
     525                                tmp1 = 0.;
     526                                if (first != second) {
     527                                        x.CopyVector((const Vector *)&first->x);
     528                                        x.SubtractVector((const Vector *)&second->x);
     529                                        tmp1 = x.Norm();
     530                                }
     531                                if ((tmp1 != 0.) && ((min[Z] == 0.) || (tmp1 < min[Z]))) min[Z] = tmp1;
     532                                //cout << Verbose(0) << "Bond length between Atom " << first->nr << " and " << second->nr << ": " << tmp1 << " a.u." << endl;
     533                        }
     534                        for (int i=MAX_ELEMENTS;i--;)
     535                                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;
     536                        break;
     537
     538                case 'b':
     539                        first = mol->AskAtom("Enter first atom: ");
     540                        second = mol->AskAtom("Enter second atom: ");
     541                        for (int i=NDIM;i--;)
     542                                min[i] = 0.;
     543                        x.CopyVector((const Vector *)&first->x);
     544                        x.SubtractVector((const Vector *)&second->x);
     545                        tmp1 = x.Norm();
     546                        cout << Verbose(1) << "Distance vector is ";
     547                        x.Output((ofstream *)&cout);
     548                        cout << "." << endl << "Norm of distance is " << tmp1 << "." << endl;
     549                        break;
     550
     551                case 'c':
     552                        cout << Verbose(0) << "Evaluating bond angle between three - first, central, last - atoms." << endl;
     553                        first = mol->AskAtom("Enter first atom: ");
     554                        second = mol->AskAtom("Enter central atom: ");
     555                        third   = mol->AskAtom("Enter last atom: ");
     556                        tmp1 = tmp2 = tmp3 = 0.;
     557                        x.CopyVector((const Vector *)&first->x);
     558                        x.SubtractVector((const Vector *)&second->x);
     559                        y.CopyVector((const Vector *)&third->x);
     560                        y.SubtractVector((const Vector *)&second->x);
     561                        cout << Verbose(0) << "Bond angle between first atom Nr." << first->nr << ", central atom Nr." << second->nr << " and last atom Nr." << third->nr << ": ";
     562                        cout << Verbose(0) << (acos(x.ScalarProduct((const Vector *)&y)/(y.Norm()*x.Norm()))/M_PI*180.) << " degrees" << endl;
     563                        break;
     564                case 'd':
     565                        cout << Verbose(0) << "Evaluating prinicipal axis." << endl;
     566                        cout << Verbose(0) << "Shall we rotate? [0/1]: ";
     567                        cin >> Z;
     568                        if ((Z >=0) && (Z <=1))
     569                                mol->PrincipalAxisSystem((ofstream *)&cout, (bool)Z);
     570                        else
     571                                mol->PrincipalAxisSystem((ofstream *)&cout, false);
     572                        break;
     573                case 'e':
     574                        cout << Verbose(0) << "Evaluating volume of the convex envelope.";
     575                        VolumeOfConvexEnvelope((ofstream *)&cout, NULL, configuration, NULL, mol);
     576                        break;
     577                case 'f':
     578                        mol->OutputTemperatureFromTrajectories((ofstream *)&cout, mol->MDSteps-1, mol->MDSteps, (ofstream *)&cout);
     579                        break;
     580                case 'g':
     581                        {
     582                                char filename[255];
     583                                cout << "Please enter filename: " << endl;
     584                                cin >> filename;
     585                                cout << Verbose(1) << "Storing temperatures in " << filename << "." << endl;
     586                                ofstream *output = new ofstream(filename, ios::trunc);
     587                                if (!mol->OutputTemperatureFromTrajectories((ofstream *)&cout, 0, mol->MDSteps, output))
     588                                        cout << Verbose(2) << "File could not be written." << endl;
     589                                else
     590                                        cout << Verbose(2) << "File stored." << endl;
     591                                output->close();
     592                                delete(output);
     593                        }
     594                        break;
     595        }
    592596};
    593597
     
    598602static void FragmentAtoms(molecule *mol, config *configuration)
    599603{
    600   int Order1;
    601   clock_t start, end;
    602 
    603   cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl;
    604   cout << Verbose(0) << "What's the desired bond order: ";
    605   cin >> Order1;
    606   if (mol->first->next != mol->last) {  // there are bonds
    607     start = clock();
    608     mol->FragmentMolecule((ofstream *)&cout, Order1, configuration);
    609     end = clock();
    610     cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
    611   } else
    612     cout << Verbose(0) << "Connection matrix has not yet been generated!" << endl;
     604        int Order1;
     605        clock_t start, end;
     606
     607        cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl;
     608        cout << Verbose(0) << "What's the desired bond order: ";
     609        cin >> Order1;
     610        if (mol->first->next != mol->last) {    // there are bonds
     611                start = clock();
     612                mol->FragmentMolecule((ofstream *)&cout, Order1, configuration);
     613                end = clock();
     614                cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
     615        } else
     616                cout << Verbose(0) << "Connection matrix has not yet been generated!" << endl;
    613617};
    614618
     
    619623static void testroutine(molecule *mol)
    620624{
    621   // the current test routine checks the functionality of the KeySet&Graph concept:
    622   // We want to have a multiindex (the KeySet) describing a unique subgraph
    623   atom *Walker = mol->start;
    624   int i, comp, counter=0;
    625 
    626   // generate some KeySets
    627   cout << "Generating KeySets." << endl;
    628   KeySet TestSets[mol->AtomCount+1];
    629   i=1;
    630   while (Walker->next != mol->end) {
    631     Walker = Walker->next;
    632     for (int j=0;j<i;j++) {
    633       TestSets[j].insert(Walker->nr);
    634     }
    635     i++;
    636   }
    637   cout << "Testing insertion of already present item in KeySets." << endl;
    638   KeySetTestPair test;
    639   test = TestSets[mol->AtomCount-1].insert(Walker->nr);
    640   if (test.second) {
    641     cout << Verbose(1) << "Insertion worked?!" << endl;
    642   } else {
    643     cout << Verbose(1) << "Insertion rejected: Present object is " << (*test.first) << "." << endl;
    644   }
    645   TestSets[mol->AtomCount].insert(mol->end->previous->nr);
    646   TestSets[mol->AtomCount].insert(mol->end->previous->previous->previous->nr);
    647 
    648   // constructing Graph structure
    649   cout << "Generating Subgraph class." << endl;
    650   Graph Subgraphs;
    651 
    652   // insert KeySets into Subgraphs
    653   cout << "Inserting KeySets into Subgraph class." << endl;
    654   for (int j=0;j<mol->AtomCount;j++) {
    655     Subgraphs.insert(GraphPair (TestSets[j],pair<int, double>(counter++, 1.)));
    656   }
    657   cout << "Testing insertion of already present item in Subgraph." << endl;
    658   GraphTestPair test2;
    659   test2 = Subgraphs.insert(GraphPair (TestSets[mol->AtomCount],pair<int, double>(counter++, 1.)));
    660   if (test2.second) {
    661     cout << Verbose(1) << "Insertion worked?!" << endl;
    662   } else {
    663     cout << Verbose(1) << "Insertion rejected: Present object is " << (*(test2.first)).second.first << "." << endl;
    664   }
    665 
    666   // show graphs
    667   cout << "Showing Subgraph's contents, checking that it's sorted." << endl;
    668   Graph::iterator A = Subgraphs.begin();
    669   while (A !=  Subgraphs.end()) {
    670     cout << (*A).second.first << ": ";
    671     KeySet::iterator key = (*A).first.begin();
    672     comp = -1;
    673     while (key != (*A).first.end()) {
    674       if ((*key) > comp)
    675         cout << (*key) << " ";
    676       else
    677         cout << (*key) << "! ";
    678       comp = (*key);
    679       key++;
    680     }
    681     cout << endl;
    682     A++;
    683   }
     625        // the current test routine checks the functionality of the KeySet&Graph concept:
     626        // We want to have a multiindex (the KeySet) describing a unique subgraph
     627        atom *Walker = mol->start;
     628        int i, comp, counter=0;
     629
     630        // generate some KeySets
     631        cout << "Generating KeySets." << endl;
     632        KeySet TestSets[mol->AtomCount+1];
     633        i=1;
     634        while (Walker->next != mol->end) {
     635                Walker = Walker->next;
     636                for (int j=0;j<i;j++) {
     637                        TestSets[j].insert(Walker->nr);
     638                }
     639                i++;
     640        }
     641        cout << "Testing insertion of already present item in KeySets." << endl;
     642        KeySetTestPair test;
     643        test = TestSets[mol->AtomCount-1].insert(Walker->nr);
     644        if (test.second) {
     645                cout << Verbose(1) << "Insertion worked?!" << endl;
     646        } else {
     647                cout << Verbose(1) << "Insertion rejected: Present object is " << (*test.first) << "." << endl;
     648        }
     649        TestSets[mol->AtomCount].insert(mol->end->previous->nr);
     650        TestSets[mol->AtomCount].insert(mol->end->previous->previous->previous->nr);
     651
     652        // constructing Graph structure
     653        cout << "Generating Subgraph class." << endl;
     654        Graph Subgraphs;
     655
     656        // insert KeySets into Subgraphs
     657        cout << "Inserting KeySets into Subgraph class." << endl;
     658        for (int j=0;j<mol->AtomCount;j++) {
     659                Subgraphs.insert(GraphPair (TestSets[j],pair<int, double>(counter++, 1.)));
     660        }
     661        cout << "Testing insertion of already present item in Subgraph." << endl;
     662        GraphTestPair test2;
     663        test2 = Subgraphs.insert(GraphPair (TestSets[mol->AtomCount],pair<int, double>(counter++, 1.)));
     664        if (test2.second) {
     665                cout << Verbose(1) << "Insertion worked?!" << endl;
     666        } else {
     667                cout << Verbose(1) << "Insertion rejected: Present object is " << (*(test2.first)).second.first << "." << endl;
     668        }
     669
     670        // show graphs
     671        cout << "Showing Subgraph's contents, checking that it's sorted." << endl;
     672        Graph::iterator A = Subgraphs.begin();
     673        while (A !=     Subgraphs.end()) {
     674                cout << (*A).second.first << ": ";
     675                KeySet::iterator key = (*A).first.begin();
     676                comp = -1;
     677                while (key != (*A).first.end()) {
     678                        if ((*key) > comp)
     679                                cout << (*key) << " ";
     680                        else
     681                                cout << (*key) << "! ";
     682                        comp = (*key);
     683                        key++;
     684                }
     685                cout << endl;
     686                A++;
     687        }
    684688};
    685689
     
    692696static void SaveConfig(char *ConfigFileName, config *configuration, periodentafel *periode, molecule *mol)
    693697{
    694   char filename[MAXSTRINGSIZE];
    695   ofstream output;
    696 
    697   cout << Verbose(0) << "Storing configuration ... " << endl;
    698   // get correct valence orbitals
    699   mol->CalculateOrbitals(*configuration);
    700   configuration->InitMaxMinStopStep = configuration->MaxMinStopStep = configuration->MaxPsiDouble;
    701   strcpy(filename, ConfigFileName);
    702   if (ConfigFileName != NULL) { // test the file name
    703     output.open(ConfigFileName, ios::trunc);
    704   } else if (strlen(configuration->configname) != 0) {
    705     strcpy(filename, configuration->configname);
    706     output.open(configuration->configname, ios::trunc);
    707     } else {
    708       strcpy(filename, DEFAULTCONFIG);
    709       output.open(DEFAULTCONFIG, ios::trunc);
    710     }
    711   output.close();
    712   output.clear();
    713   cout << Verbose(0) << "Saving of config file ";
    714   if (configuration->Save(filename, periode, mol))
    715     cout << "successful." << endl;
    716   else
    717     cout << "failed." << endl;
    718 
    719   // and save to xyz file
    720   if (ConfigFileName != NULL) {
    721     strcpy(filename, ConfigFileName);
    722     strcat(filename, ".xyz");
    723     output.open(filename, ios::trunc);
    724   }
    725   if (output == NULL) {
    726     strcpy(filename,"main_pcp_linux");
    727     strcat(filename, ".xyz");
    728     output.open(filename, ios::trunc);
    729   }
    730   cout << Verbose(0) << "Saving of XYZ file ";
    731   if (mol->MDSteps <= 1) {
    732     if (mol->OutputXYZ(&output))
    733       cout << "successful." << endl;
    734     else
    735       cout << "failed." << endl;
    736   } else {
    737     if (mol->OutputTrajectoriesXYZ(&output))
    738       cout << "successful." << endl;
    739     else
    740       cout << "failed." << endl;
    741   }
    742   output.close();
    743   output.clear();
    744 
    745   // and save as MPQC configuration
    746   if (ConfigFileName != NULL)
    747     strcpy(filename, ConfigFileName);
    748   if (output == NULL)
    749     strcpy(filename,"main_pcp_linux");
    750   cout << Verbose(0) << "Saving as mpqc input ";
    751   if (configuration->SaveMPQC(filename, mol))
    752     cout << "done." << endl;
    753   else
    754     cout << "failed." << endl;
    755 
    756   if (!strcmp(configuration->configpath, configuration->GetDefaultPath())) {
    757     cerr << "WARNING: config is found under different path then stated in config file::defaultpath!" << endl;
    758   }
     698        char filename[MAXSTRINGSIZE];
     699        ofstream output;
     700
     701        cout << Verbose(0) << "Storing configuration ... " << endl;
     702        // get correct valence orbitals
     703        mol->CalculateOrbitals(*configuration);
     704        configuration->InitMaxMinStopStep = configuration->MaxMinStopStep = configuration->MaxPsiDouble;
     705        strcpy(filename, ConfigFileName);
     706        if (ConfigFileName != NULL) { // test the file name
     707                output.open(ConfigFileName, ios::trunc);
     708        } else if (strlen(configuration->configname) != 0) {
     709                strcpy(filename, configuration->configname);
     710                output.open(configuration->configname, ios::trunc);
     711                } else {
     712                        strcpy(filename, DEFAULTCONFIG);
     713                        output.open(DEFAULTCONFIG, ios::trunc);
     714                }
     715        output.close();
     716        output.clear();
     717        cout << Verbose(0) << "Saving of config file ";
     718        if (configuration->Save(filename, periode, mol))
     719                cout << "successful." << endl;
     720        else
     721                cout << "failed." << endl;
     722
     723        // and save to xyz file
     724        if (ConfigFileName != NULL) {
     725                strcpy(filename, ConfigFileName);
     726                strcat(filename, ".xyz");
     727                output.open(filename, ios::trunc);
     728        }
     729        if (output == NULL) {
     730                strcpy(filename,"main_pcp_linux");
     731                strcat(filename, ".xyz");
     732                output.open(filename, ios::trunc);
     733        }
     734        cout << Verbose(0) << "Saving of XYZ file ";
     735        if (mol->MDSteps <= 1) {
     736                if (mol->OutputXYZ(&output))
     737                        cout << "successful." << endl;
     738                else
     739                        cout << "failed." << endl;
     740        } else {
     741                if (mol->OutputTrajectoriesXYZ(&output))
     742                        cout << "successful." << endl;
     743                else
     744                        cout << "failed." << endl;
     745        }
     746        output.close();
     747        output.clear();
     748
     749        // and save as MPQC configuration
     750        if (ConfigFileName != NULL)
     751                strcpy(filename, ConfigFileName);
     752        if (output == NULL)
     753                strcpy(filename,"main_pcp_linux");
     754        cout << Verbose(0) << "Saving as mpqc input ";
     755        if (configuration->SaveMPQC(filename, mol))
     756                cout << "done." << endl;
     757        else
     758                cout << "failed." << endl;
     759
     760        if (!strcmp(configuration->configpath, configuration->GetDefaultPath())) {
     761                cerr << "WARNING: config is found under different path then stated in config file::defaultpath!" << endl;
     762        }
    759763};
    760764
     
    771775static int ParseCommandLineOptions(int argc, char **argv, molecule *&mol, periodentafel *&periode, config& configuration, char *&ConfigFileName, char *&PathToDatabases)
    772776{
    773   Vector x,y,z,n;  // coordinates for absolute point in cell volume
    774   double *factor; // unit factor if desired
    775   ifstream test;
    776   ofstream output;
    777   string line;
    778   atom *first;
    779   bool SaveFlag = false;
    780   int ExitFlag = 0;
    781   int j;
    782   double volume = 0.;
    783   enum ConfigStatus config_present = absent;
    784   clock_t start,end;
    785   int argptr;
    786   PathToDatabases = LocalPath;
    787 
    788   if (argc > 1) { // config file specified as option
    789     // 1. : Parse options that just set variables or print help
    790     argptr = 1;
    791     do {
    792       if (argv[argptr][0] == '-') {
    793         cout << Verbose(0) << "Recognized command line argument: " << argv[argptr][1] << ".\n";
    794         argptr++;
    795         switch(argv[argptr-1][1]) {
    796           case 'h':
    797           case 'H':
    798           case '?':
    799             cout << "MoleCuilder suite" << endl << "==================" << endl << endl;
    800             cout << "Usage: " << argv[0] << "[config file] [-{acefpsthH?vfrp}] [further arguments]" << endl;
    801             cout << "or simply " << argv[0] << " without arguments for interactive session." << endl;
    802             cout << "\t-a Z x1 x2 x3\tAdd new atom of element Z at coordinates (x1,x2,x3)." << endl;
    803             cout << "\t-A <source>\tCreate adjacency list from bonds parsed from 'dbond'-style file." <<endl;
    804             cout << "\t-b x1 x2 x3\tCenter atoms in domain with given edge lengths of (x1,x2,x3)." << endl;
    805             cout << "\t-c x1 x2 x3\tCenter atoms in domain with a minimum distance to boundary of (x1,x2,x3)." << endl;
    806             cout << "\t-D <bond distance>\tDepth-First-Search Analysis of the molecule, giving cycles and tree/back edges." << endl;
    807             cout << "\t-O\tCenter atoms in origin." << endl;
    808             cout << "\t-d x1 x2 x3\tDuplicate cell along each axis by given factor." << endl;
    809             cout << "\t-e <file>\tSets the databases path to be parsed (default: ./)." << endl;
    810             cout << "\t-E <id> <Z>\tChange atom <id>'s element to <Z>, <id> begins at 0." << endl;
    811             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;
    812             cout << "\t-h/-H/-?\tGive this help screen." << endl;
    813             cout << "\t-m <0/1>\tCalculate (0)/ Align in(1) PAS with greatest EV along z axis." << endl;
    814             cout << "\t-n\tFast parsing (i.e. no trajectories are looked for)." << endl;
    815             cout << "\t-N\tGet non-convex-envelope." << endl;
    816             cout << "\t-o <out>\tGet volume of the convex envelope (and store to tecplot file)." << endl;
    817             cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl;
    818             cout << "\t-P <file>\tParse given forces file and append as an MD step to config file via Verlet." << endl;
    819             cout << "\t-r\t\tConvert file from an old pcp syntax." << endl;
    820             cout << "\t-t x1 x2 x3\tTranslate all atoms by this vector (x1,x2,x3)." << endl;
    821             cout << "\t-T <file> Store temperatures from the config file in <file>." << endl;
    822             cout << "\t-s x1 x2 x3\tScale all atom coordinates by this vector (x1,x2,x3)." << endl;
    823             cout << "\t-u rho\tsuspend in water solution and output necessary cell lengths, average density rho and repetition." << endl;
    824             cout << "\t-v/-V\t\tGives version information." << endl;
    825             cout << "Note: config files must not begin with '-' !" << endl;
    826             delete(mol);
    827             delete(periode);
    828             return (1);
    829             break;
    830           case 'v':
    831           case 'V':
    832             cout << argv[0] << " " << VERSIONSTRING << endl;
    833             cout << "Build your own molecule position set." << endl;
    834             delete(mol);
    835             delete(periode);
    836             return (1);
    837             break;
    838           case 'e':
    839             if ((argptr >= argc) || (argv[argptr][0] == '-')) {
    840               cerr << "Not enough or invalid arguments for specifying element db: -e <db file>" << endl;
    841             } else {
    842               cout << "Using " << argv[argptr] << " as elements database." << endl;
    843               PathToDatabases = argv[argptr];
    844               argptr+=1;
    845             }
    846             break;
    847           case 'n':
    848             cout << "I won't parse trajectories." << endl;
    849             configuration.FastParsing = true;
    850             break;
    851           default:  // no match? Step on
    852             argptr++;
    853             break;
    854         }
    855       } else
    856         argptr++;
    857     } while (argptr < argc);
    858 
    859     // 2. Parse the element database
    860     if (periode->LoadPeriodentafel(PathToDatabases)) {
    861       cout << Verbose(0) << "Element list loaded successfully." << endl;
    862       //periode->Output((ofstream *)&cout);
    863     } else {
    864       cout << Verbose(0) << "Element list loading failed." << endl;
    865       return 1;
    866     }
    867 
    868     // 3. Find config file name and parse if possible
    869     if (argv[1][0] != '-') {
    870       cout << Verbose(0) << "Config file given." << endl;
    871       test.open(argv[1], ios::in);
    872       if (test == NULL) {
    873         //return (1);
    874         output.open(argv[1], ios::out);
    875         if (output == NULL) {
    876           cout << Verbose(1) << "Specified config file " << argv[1] << " not found." << endl;
    877           config_present = absent;
    878         } else {
    879           cout << "Empty configuration file." << endl;
    880           ConfigFileName = argv[1];
    881           config_present = empty;
    882           output.close();
    883         }
    884       } else {
    885         test.close();
    886         ConfigFileName = argv[1];
    887         cout << Verbose(1) << "Specified config file found, parsing ... ";
    888         switch (configuration.TestSyntax(ConfigFileName, periode, mol)) {
    889           case 1:
    890             cout << "new syntax." << endl;
    891             configuration.Load(ConfigFileName, periode, mol);
    892             config_present = present;
    893             break;
    894           case 0:
    895             cout << "old syntax." << endl;
    896             configuration.LoadOld(ConfigFileName, periode, mol);
    897             config_present = present;
    898             break;
    899           default:
    900             cout << "Unknown syntax or empty, yet present file." << endl;
    901             config_present = empty;
    902        }
    903       }
    904     } else
    905       config_present = absent;
    906 
    907     // 4. parse again through options, now for those depending on elements db and config presence
    908     argptr = 1;
    909     do {
    910       cout << "Current Command line argument: " << argv[argptr] << "." << endl;
    911       if (argv[argptr][0] == '-') {
    912         argptr++;
    913         if ((config_present == present) || (config_present == empty)) {
    914           switch(argv[argptr-1][1]) {
    915             case 'p':
    916               ExitFlag = 1;
    917               if ((argptr >= argc) || (argv[argptr][0] == '-')) {
    918                 ExitFlag = 255;
    919                 cerr << "Not enough arguments for parsing: -p <xyz file>" << endl;
    920               } else {
    921                 SaveFlag = true;
    922                 cout << Verbose(1) << "Parsing xyz file for new atoms." << endl;
    923                 if (!mol->AddXYZFile(argv[argptr]))
    924                   cout << Verbose(2) << "File not found." << endl;
    925                 else {
    926                   cout << Verbose(2) << "File found and parsed." << endl;
    927                   config_present = present;
    928                 }
    929               }
    930               break;
    931             case 'a':
    932               ExitFlag = 1;
    933               if ((argptr >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr+1]))) {
    934                 ExitFlag = 255;
    935                 cerr << "Not enough or invalid arguments for adding atom: -a <element> <x> <y> <z>" << endl;
    936               } else {
    937                 SaveFlag = true;
    938                 cout << Verbose(1) << "Adding new atom with element " << argv[argptr] << " at (" << argv[argptr+1] << "," << argv[argptr+2] << "," << argv[argptr+3] << "), ";
    939                 first = new atom;
    940                 first->type = periode->FindElement(atoi(argv[argptr]));
    941                 if (first->type != NULL)
    942                   cout << Verbose(2) << "found element " << first->type->name << endl;
    943                 for (int i=NDIM;i--;)
    944                   first->x.x[i] = atof(argv[argptr+1+i]);
    945                 if (first->type != NULL) {
    946                   mol->AddAtom(first);  // add to molecule
    947                   if ((config_present == empty) && (mol->AtomCount != 0))
    948                     config_present = present;
    949                 } else
    950                   cerr << Verbose(1) << "Could not find the specified element." << endl;
    951                 argptr+=4;
    952               }
    953               break;
    954             default:   // no match? Don't step on (this is done in next switch's default)
    955               break;
    956           }
    957         }
    958         if (config_present == present) {
    959           switch(argv[argptr-1][1]) {
    960             case 'D':
    961               ExitFlag = 1;
    962               {
    963                 cout << Verbose(1) << "Depth-First-Search Analysis." << endl;
    964                 MoleculeLeafClass *Subgraphs = NULL;      // list of subgraphs from DFS analysis
    965                 int *MinimumRingSize = new int[mol->AtomCount];
    966                 atom ***ListOfLocalAtoms = NULL;
    967                 int FragmentCounter = 0;
    968                 class StackClass<bond *> *BackEdgeStack = NULL;
    969                 class StackClass<bond *> *LocalBackEdgeStack = NULL;
    970                 mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr]), configuration.GetIsAngstroem());
    971                 mol->CreateListOfBondsPerAtom((ofstream *)&cout);
    972                 Subgraphs = mol->DepthFirstSearchAnalysis((ofstream *)&cout, BackEdgeStack);
    973                 if (Subgraphs != NULL) {
    974                   Subgraphs->next->FillBondStructureFromReference((ofstream *)&cout, mol, (FragmentCounter = 0), ListOfLocalAtoms, false);  // we want to keep the created ListOfLocalAtoms
    975                   while (Subgraphs->next != NULL) {
    976                     Subgraphs = Subgraphs->next;
    977                     LocalBackEdgeStack = new StackClass<bond *> (Subgraphs->Leaf->BondCount);
    978                     Subgraphs->Leaf->PickLocalBackEdges((ofstream *)&cout, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack);
    979                     Subgraphs->Leaf->CyclicStructureAnalysis((ofstream *)&cout, BackEdgeStack, MinimumRingSize);
    980                     delete(LocalBackEdgeStack);
    981                     delete(Subgraphs->previous);
    982                   }
    983                   delete(Subgraphs);
    984                   for (int i=0;i<FragmentCounter;i++)
    985                     Free((void **)&ListOfLocalAtoms[FragmentCounter], "ParseCommandLineOptions: **ListOfLocalAtoms[]");
    986                   Free((void **)&ListOfLocalAtoms, "ParseCommandLineOptions: ***ListOfLocalAtoms");
    987                 }
    988                 delete(BackEdgeStack);
    989                 delete[](MinimumRingSize);
    990               }
    991               //argptr+=1;
    992               break;
    993             case 'E':
    994               ExitFlag = 1;
    995               if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (argv[argptr+1][0] == '-')) {
    996                 ExitFlag = 255;
    997                 cerr << "Not enough or invalid arguments given for changing element: -E <atom nr.> <element>" << endl;
    998               } else {
    999                 SaveFlag = true;
    1000                 cout << Verbose(1) << "Changing atom " << argv[argptr] << " to element " << argv[argptr+1] << "." << endl;
    1001                 first = mol->FindAtom(atoi(argv[argptr]));
    1002                 first->type = periode->FindElement(atoi(argv[argptr+1]));
    1003                 argptr+=2;
    1004               }
    1005               break;
    1006             case 'A':
    1007                 ExitFlag = 1;
    1008                 if ((argptr >= argc) || (argv[argptr][0] == '-')){
    1009                         ExitFlag =255;
    1010                         cerr << "Missing source file for bonds in molecule: -A <bond sourcefile>" << endl;
    1011                 }
    1012                 else{
    1013                         cout << "Parsing bonds from " << argv[argptr] << "." << endl;
    1014                     ifstream *input = new ifstream(argv[argptr]);
    1015                         mol->CreateAdjacencyList2((ofstream *)&cout, input);
    1016                         input->close();
    1017                 }
    1018                 break;
    1019             case 'N':
    1020                 ExitFlag = 1;
    1021                 if ((argptr >= argc) || (argv[argptr][0] == '-')){
    1022                         ExitFlag = 255;
    1023                         cerr << "Not enough or invalid arguments given for non-convex envelope: -o <tecplot output file>" << endl;
    1024                         }
    1025                 else {
    1026                         cout << Verbose(0) << "Evaluating npn-convex envelope.";
    1027                         cout << Verbose(1) << "Storing tecplot data in " << argv[argptr] << "." << endl;
    1028                         Find_non_convex_border((ofstream *)&cout, argv[argptr], mol);
    1029                         argptr+=1;
    1030                         }
    1031                 break;
    1032             case 'T':
    1033               ExitFlag = 1;
    1034               if ((argptr >= argc) || (argv[argptr][0] == '-')) {
    1035                 ExitFlag = 255;
    1036                 cerr << "Not enough or invalid arguments given for storing temperature: -T <temperature file>" << endl;
    1037               } else {
    1038                 cout << Verbose(1) << "Storing temperatures in " << argv[argptr] << "." << endl;
    1039                 ofstream *output = new ofstream(argv[argptr], ios::trunc);
    1040                 if (!mol->OutputTemperatureFromTrajectories((ofstream *)&cout, 0, mol->MDSteps, output))
    1041                   cout << Verbose(2) << "File could not be written." << endl;
    1042                 else
    1043                   cout << Verbose(2) << "File stored." << endl;
    1044                 output->close();
    1045                 delete(output);
    1046                 argptr+=1;
    1047               }
    1048               break;
    1049             case 'P':
    1050               ExitFlag = 1;
    1051               if ((argptr >= argc) || (argv[argptr][0] == '-')) {
    1052                 ExitFlag = 255;
    1053                 cerr << "Not enough or invalid arguments given for parsing and integrating forces: -P <forces file>" << endl;
    1054               } else {
    1055                 SaveFlag = true;
    1056                 cout << Verbose(1) << "Parsing forces file and Verlet integrating." << endl;
    1057                 if (!mol->VerletForceIntegration(argv[argptr], configuration.Deltat, configuration.GetIsAngstroem()))
    1058                   cout << Verbose(2) << "File not found." << endl;
    1059                 else
    1060                   cout << Verbose(2) << "File found and parsed." << endl;
    1061                 argptr+=1;
    1062               }
    1063               break;
    1064             case 't':
    1065               ExitFlag = 1;
    1066               if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
    1067                 ExitFlag = 255;
    1068                 cerr << "Not enough or invalid arguments given for translation: -t <x> <y> <z>" << endl;
    1069               } else {
    1070                 ExitFlag = 1;
    1071                 SaveFlag = true;
    1072                 cout << Verbose(1) << "Translating all ions to new origin." << endl;
    1073                 for (int i=NDIM;i--;)
    1074                   x.x[i] = atof(argv[argptr+i]);
    1075                 mol->Translate((const Vector *)&x);
    1076                 argptr+=3;
    1077               }
    1078               break;
    1079             case 's':
    1080               ExitFlag = 1;
    1081               if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) {
    1082                 ExitFlag = 255;
    1083                 cerr << "Not enough or invalid arguments given for scaling: -s <factor/[factor_x]> [factor_y] [factor_z]" << endl;
    1084               } else {
    1085                 SaveFlag = true;
    1086                 j = -1;
    1087                 cout << Verbose(1) << "Scaling all ion positions by factor." << endl;
    1088                 factor = new double[NDIM];
    1089                 factor[0] = atof(argv[argptr]);
    1090                 if ((argptr < argc) && (IsValidNumber(argv[argptr])))
    1091                   argptr++;
    1092                 factor[1] = atof(argv[argptr]);
    1093                 if ((argptr < argc) && (IsValidNumber(argv[argptr])))
    1094                   argptr++;
    1095                 factor[2] = atof(argv[argptr]);
    1096                 mol->Scale(&factor);
    1097                 for (int i=0;i<NDIM;i++) {
    1098                   j += i+1;
    1099                   x.x[i] = atof(argv[NDIM+i]);
    1100                   mol->cell_size[j]*=factor[i];
    1101                 }
    1102                 delete[](factor);
    1103                 argptr+=1;
    1104               }
    1105               break;
    1106             case 'b':
    1107               ExitFlag = 1;
    1108               if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
    1109                 ExitFlag = 255;
    1110                 cerr << "Not enough or invalid arguments given for centering in box: -b <length_x> <length_y> <length_z>" << endl;
    1111               } else {
    1112                 SaveFlag = true;
    1113                 j = -1;
    1114                 cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl;
    1115                 j=-1;
    1116                 for (int i=0;i<NDIM;i++) {
    1117                   j += i+1;
    1118                   x.x[i] = atof(argv[argptr++]);
    1119                   mol->cell_size[j] += x.x[i]*2.;
    1120                 }
    1121                 // center
    1122                 mol->CenterInBox((ofstream *)&cout, &x);
    1123                 // update Box of atoms by boundary
    1124                 mol->SetBoxDimension(&x);
    1125               }
    1126               break;
    1127             case 'c':
    1128               ExitFlag = 1;
    1129               if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
    1130                 ExitFlag = 255;
    1131                 cerr << "Not enough or invalid arguments given for centering with boundary: -c <boundary_x> <boundary_y> <boundary_z>" << endl;
    1132               } else {
    1133                 SaveFlag = true;
    1134                 j = -1;
    1135                 cout << Verbose(1) << "Centering atoms in config file within given additional boundary." << endl;
    1136                 // make every coordinate positive
    1137                 mol->CenterEdge((ofstream *)&cout, &x);
    1138                 // update Box of atoms by boundary
    1139                 mol->SetBoxDimension(&x);
    1140                 // translate each coordinate by boundary
    1141                 j=-1;
    1142                 for (int i=0;i<NDIM;i++) {
    1143                   j += i+1;
    1144                   x.x[i] = atof(argv[argptr++]);
    1145                   mol->cell_size[j] += x.x[i]*2.;
    1146                 }
    1147                 mol->Translate((const Vector *)&x);
    1148               }
    1149               break;
    1150             case 'O':
    1151               ExitFlag = 1;
    1152               SaveFlag = true;
    1153               cout << Verbose(1) << "Centering atoms in origin." << endl;
    1154               mol->CenterOrigin((ofstream *)&cout, &x);
    1155               mol->SetBoxDimension(&x);
    1156               break;
    1157             case 'r':
    1158               ExitFlag = 1;
    1159               SaveFlag = true;
    1160               cout << Verbose(1) << "Converting config file from supposed old to new syntax." << endl;
    1161               break;
    1162             case 'F':
    1163             case 'f':
    1164               ExitFlag = 1;
    1165               if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1]))) {
    1166                 ExitFlag = 255;
    1167                 cerr << "Not enough or invalid arguments for fragmentation: -f <max. bond distance> <bond order>" << endl;
    1168               } else {
    1169                 cout << "Fragmenting molecule with bond distance " << argv[argptr] << " angstroem, order of " << argv[argptr+1] << "." << endl;
    1170                 cout << Verbose(0) << "Creating connection matrix..." << endl;
    1171                 start = clock();
    1172                 mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr++]), configuration.GetIsAngstroem());
    1173                 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl;
    1174                 if (mol->first->next != mol->last) {
    1175                   ExitFlag = mol->FragmentMolecule((ofstream *)&cout, atoi(argv[argptr]), &configuration);
    1176                 }
    1177                 end = clock();
    1178                 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
    1179                 argptr+=2;
    1180               }
    1181               break;
    1182             case 'm':
    1183               ExitFlag = 1;
    1184               j = atoi(argv[argptr++]);
    1185               if ((j<0) || (j>1)) {
    1186                 cerr << Verbose(1) << "ERROR: Argument of '-m' should be either 0 for no-rotate or 1 for rotate." << endl;
    1187                 j = 0;
    1188               }
    1189               if (j) {
    1190                 SaveFlag = true;
    1191                 cout << Verbose(0) << "Converting to prinicipal axis system." << endl;
    1192               } else
    1193                 cout << Verbose(0) << "Evaluating prinicipal axis." << endl;
    1194               mol->PrincipalAxisSystem((ofstream *)&cout, (bool)j);
    1195               break;
    1196             case 'o':
    1197               ExitFlag = 1;
    1198               if ((argptr >= argc) || (argv[argptr][0] == '-')){
    1199                 ExitFlag = 255;
    1200                 cerr << "Not enough or invalid arguments given for convex envelope: -o <tecplot output file>" << endl;
    1201               } else {
    1202                 cout << Verbose(0) << "Evaluating volume of the convex envelope.";
    1203                 ofstream *output = new ofstream(argv[argptr], ios::trunc);
    1204                 //$$$
    1205                 cout << Verbose(1) << "Storing tecplot data in " << argv[argptr] << "." << endl;
    1206                 VolumeOfConvexEnvelope((ofstream *)&cout, output, &configuration, NULL, mol);
    1207                 output->close();
    1208                 delete(output);
    1209                 argptr+=1;
    1210               }
    1211               break;
    1212             case 'U':
    1213               ExitFlag = 1;
    1214               if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) ) {
    1215                 ExitFlag = 255;
    1216                 cerr << "Not enough or invalid arguments given for suspension with specified volume: -U <volume> <density>" << endl;
    1217                 volume = -1; // for case 'u': don't print error again
    1218               } else {
    1219                 volume = atof(argv[argptr++]);
    1220                 cout << Verbose(0) << "Using " << volume << " angstrom^3 as the volume instead of convex envelope one's." << endl;
    1221               }
    1222             case 'u':
    1223               ExitFlag = 1;
    1224               if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) {
    1225                 if (volume != -1)
    1226                   ExitFlag = 255;
    1227                   cerr << "Not enough arguments given for suspension: -u <density>" << endl;
    1228               } else {
    1229                 double density;
    1230                 SaveFlag = true;
    1231                 cout << Verbose(0) << "Evaluating necessary cell volume for a cluster suspended in water.";
    1232                 density = atof(argv[argptr++]);
    1233                 if (density < 1.0) {
    1234                   cerr << Verbose(0) << "Density must be greater than 1.0g/cm^3 !" << endl;
    1235                   density = 1.3;
    1236                 }
    1237 //                for(int i=0;i<NDIM;i++) {
    1238 //                  repetition[i] = atoi(argv[argptr++]);
    1239 //                  if (repetition[i] < 1)
    1240 //                    cerr << Verbose(0) << "ERROR: repetition value must be greater 1!" << endl;
    1241 //                  repetition[i] = 1;
    1242 //                }
    1243                 PrepareClustersinWater((ofstream *)&cout, &configuration, mol, volume, density);  // if volume == 0, will calculate from ConvexEnvelope
    1244               }
    1245               break;
    1246             case 'd':
    1247               ExitFlag = 1;
    1248               if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
    1249                 ExitFlag = 255;
    1250                 cerr << "Not enough or invalid arguments given for repeating cells: -d <repeat_x> <repeat_y> <repeat_z>" << endl;
    1251               } else {
    1252                 SaveFlag = true;
    1253                 for (int axis = 1; axis <= NDIM; axis++) {
    1254                   int faktor = atoi(argv[argptr++]);
    1255                   int count;
    1256                   element ** Elements;
    1257                   Vector ** vectors;
    1258                   if (faktor < 1) {
    1259                     cerr << Verbose(0) << "ERROR: Repetition faktor mus be greater than 1!" << endl;
    1260                     faktor = 1;
    1261                   }
    1262                   mol->CountAtoms((ofstream *)&cout);  // recount atoms
    1263                   if (mol->AtomCount != 0) {  // if there is more than none
    1264                     count = mol->AtomCount;  // is changed becausing of adding, thus has to be stored away beforehand
    1265                     Elements = new element *[count];
    1266                     vectors = new Vector *[count];
    1267                     j = 0;
    1268                     first = mol->start;
    1269                     while (first->next != mol->end) {  // make a list of all atoms with coordinates and element
    1270                       first = first->next;
    1271                       Elements[j] = first->type;
    1272                       vectors[j] = &first->x;
    1273                       j++;
    1274                     }
    1275                     if (count != j)
    1276                       cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl;
    1277                     x.Zero();
    1278                     y.Zero();
    1279                     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
    1280                     for (int i=1;i<faktor;i++) {  // then add this list with respective translation factor times
    1281                       x.AddVector(&y); // per factor one cell width further
    1282                       for (int k=count;k--;) { // go through every atom of the original cell
    1283                         first = new atom(); // create a new body
    1284                         first->x.CopyVector(vectors[k]);  // use coordinate of original atom
    1285                         first->x.AddVector(&x);      // translate the coordinates
    1286                         first->type = Elements[k];  // insert original element
    1287                         mol->AddAtom(first);        // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...)
    1288                       }
    1289                     }
    1290                     // free memory
    1291                     delete[](Elements);
    1292                     delete[](vectors);
    1293                     // correct cell size
    1294                     if (axis < 0) { // if sign was negative, we have to translate everything
    1295                       x.Zero();
    1296                       x.AddVector(&y);
    1297                       x.Scale(-(faktor-1));
    1298                       mol->Translate(&x);
    1299                     }
    1300                     mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor;
    1301                   }
    1302                 }
    1303               }
    1304               break;
    1305             default:  // no match? Step on
    1306               if ((argptr < argc) && (argv[argptr][0] != '-')) // if it started with a '-' we've already made a step!
    1307                 argptr++;
    1308               break;
    1309           }
    1310         }
    1311       } else argptr++;
    1312     } while (argptr < argc);
    1313     if (SaveFlag)
    1314       SaveConfig(ConfigFileName, &configuration, periode, mol);
    1315     if ((ExitFlag >= 1)) {
    1316       delete(mol);
    1317       delete(periode);
    1318       return (ExitFlag);
    1319     }
    1320   } else {  // no arguments, hence scan the elements db
    1321     if (periode->LoadPeriodentafel(PathToDatabases))
    1322       cout << Verbose(0) << "Element list loaded successfully." << endl;
    1323     else
    1324       cout << Verbose(0) << "Element list loading failed." << endl;
    1325     configuration.RetrieveConfigPathAndName("main_pcp_linux");
    1326   }
    1327   return(0);
     777        Vector x,y,z,n; // coordinates for absolute point in cell volume
     778        double *factor; // unit factor if desired
     779        ifstream test;
     780        ofstream output;
     781        string line;
     782        atom *first;
     783        bool SaveFlag = false;
     784        int ExitFlag = 0;
     785        int j;
     786        double volume = 0.;
     787        enum ConfigStatus config_present = absent;
     788        clock_t start,end;
     789        int argptr;
     790        PathToDatabases = LocalPath;
     791
     792        if (argc > 1) { // config file specified as option
     793                // 1. : Parse options that just set variables or print help
     794                argptr = 1;
     795                do {
     796                        if (argv[argptr][0] == '-') {
     797                                cout << Verbose(0) << "Recognized command line argument: " << argv[argptr][1] << ".\n";
     798                                argptr++;
     799                                switch(argv[argptr-1][1]) {
     800                                        case 'h':
     801                                        case 'H':
     802                                        case '?':
     803                                                cout << "MoleCuilder suite" << endl << "==================" << endl << endl;
     804                                                cout << "Usage: " << argv[0] << "[config file] [-{acefpsthH?vfrp}] [further arguments]" << endl;
     805                                                cout << "or simply " << argv[0] << " without arguments for interactive session." << endl;
     806                                                cout << "\t-a Z x1 x2 x3\tAdd new atom of element Z at coordinates (x1,x2,x3)." << endl;
     807                                                cout << "\t-A <source>\tCreate adjacency list from bonds parsed from 'dbond'-style file." <<endl;
     808                                                cout << "\t-b x1 x2 x3\tCenter atoms in domain with given edge lengths of (x1,x2,x3)." << endl;
     809                                                cout << "\t-c x1 x2 x3\tCenter atoms in domain with a minimum distance to boundary of (x1,x2,x3)." << endl;
     810                                                cout << "\t-D <bond distance>\tDepth-First-Search Analysis of the molecule, giving cycles and tree/back edges." << endl;
     811                                                cout << "\t-O\tCenter atoms in origin." << endl;
     812                                                cout << "\t-d x1 x2 x3\tDuplicate cell along each axis by given factor." << endl;
     813                                                cout << "\t-e <file>\tSets the databases path to be parsed (default: ./)." << endl;
     814                                                cout << "\t-E <id> <Z>\tChange atom <id>'s element to <Z>, <id> begins at 0." << endl;
     815                                                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;
     816                                                cout << "\t-h/-H/-?\tGive this help screen." << endl;
     817                                                cout << "\t-m <0/1>\tCalculate (0)/ Align in(1) PAS with greatest EV along z axis." << endl;
     818                                                cout << "\t-n\tFast parsing (i.e. no trajectories are looked for)." << endl;
     819                                                cout << "\t-N\tGet non-convex-envelope." << endl;
     820                                                cout << "\t-o <out>\tGet volume of the convex envelope (and store to tecplot file)." << endl;
     821                                                cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl;
     822                                                cout << "\t-P <file>\tParse given forces file and append as an MD step to config file via Verlet." << endl;
     823                                                cout << "\t-r\t\tConvert file from an old pcp syntax." << endl;
     824                                                cout << "\t-t x1 x2 x3\tTranslate all atoms by this vector (x1,x2,x3)." << endl;
     825                                                cout << "\t-T <file> Store temperatures from the config file in <file>." << endl;
     826                                                cout << "\t-s x1 x2 x3\tScale all atom coordinates by this vector (x1,x2,x3)." << endl;
     827                                                cout << "\t-u rho\tsuspend in water solution and output necessary cell lengths, average density rho and repetition." << endl;
     828                                                cout << "\t-v/-V\t\tGives version information." << endl;
     829                                                cout << "Note: config files must not begin with '-' !" << endl;
     830                                                delete(mol);
     831                                                delete(periode);
     832                                                return (1);
     833                                                break;
     834                                        case 'v':
     835                                        case 'V':
     836                                                cout << argv[0] << " " << VERSIONSTRING << endl;
     837                                                cout << "Build your own molecule position set." << endl;
     838                                                delete(mol);
     839                                                delete(periode);
     840                                                return (1);
     841                                                break;
     842                                        case 'e':
     843                                                if ((argptr >= argc) || (argv[argptr][0] == '-')) {
     844                                                        cerr << "Not enough or invalid arguments for specifying element db: -e <db file>" << endl;
     845                                                } else {
     846                                                        cout << "Using " << argv[argptr] << " as elements database." << endl;
     847                                                        PathToDatabases = argv[argptr];
     848                                                        argptr+=1;
     849                                                }
     850                                                break;
     851                                        case 'n':
     852                                                cout << "I won't parse trajectories." << endl;
     853                                                configuration.FastParsing = true;
     854                                                break;
     855                                        default:        // no match? Step on
     856                                                argptr++;
     857                                                break;
     858                                }
     859                        } else
     860                                argptr++;
     861                } while (argptr < argc);
     862
     863                // 2. Parse the element database
     864                if (periode->LoadPeriodentafel(PathToDatabases)) {
     865                        cout << Verbose(0) << "Element list loaded successfully." << endl;
     866                        //periode->Output((ofstream *)&cout);
     867                } else {
     868                        cout << Verbose(0) << "Element list loading failed." << endl;
     869                        return 1;
     870                }
     871                // 3. Find config file name and parse if possible
     872                if (argv[1][0] != '-') {
     873                        cout << Verbose(0) << "Config file given." << endl;
     874                        test.open(argv[1], ios::in);
     875                        if (test == NULL) {
     876                                //return (1);
     877                                output.open(argv[1], ios::out);
     878                                if (output == NULL) {
     879                                        cout << Verbose(1) << "Specified config file " << argv[1] << " not found." << endl;
     880                                        config_present = absent;
     881                                } else {
     882                                        cout << "Empty configuration file." << endl;
     883                                        ConfigFileName = argv[1];
     884                                        config_present = empty;
     885                                        output.close();
     886                                }
     887                        } else {
     888                                test.close();
     889                                ConfigFileName = argv[1];
     890                                cout << Verbose(1) << "Specified config file found, parsing ... ";
     891                                switch (configuration.TestSyntax(ConfigFileName, periode, mol)) {
     892                                        case 1:
     893                                                cout << "new syntax." << endl;
     894                                                configuration.Load(ConfigFileName, periode, mol);
     895                                                config_present = present;
     896                                                break;
     897                                        case 0:
     898                                                cout << "old syntax." << endl;
     899                                                configuration.LoadOld(ConfigFileName, periode, mol);
     900                                                config_present = present;
     901                                                break;
     902                                        default:
     903                                                cout << "Unknown syntax or empty, yet present file." << endl;
     904                                                config_present = empty;
     905                         }
     906                        }
     907                } else
     908                        config_present = absent;
     909                // 4. parse again through options, now for those depending on elements db and config presence
     910                argptr = 1;
     911                do {
     912                        cout << "Current Command line argument: " << argv[argptr] << "." << endl;
     913                        if (argv[argptr][0] == '-') {
     914                                argptr++;
     915                                if ((config_present == present) || (config_present == empty)) {
     916                                        switch(argv[argptr-1][1]) {
     917                                                case 'p':
     918                                                        ExitFlag = 1;
     919                                                        if ((argptr >= argc) || (argv[argptr][0] == '-')) {
     920                                                                ExitFlag = 255;
     921                                                                cerr << "Not enough arguments for parsing: -p <xyz file>" << endl;
     922                                                        } else {
     923                                                                SaveFlag = true;
     924                                                                cout << Verbose(1) << "Parsing xyz file for new atoms." << endl;
     925                                                                if (!mol->AddXYZFile(argv[argptr]))
     926                                                                        cout << Verbose(2) << "File not found." << endl;
     927                                                                else {
     928                                                                        cout << Verbose(2) << "File found and parsed." << endl;
     929                                                                        config_present = present;
     930                                                                }
     931                                                        }
     932                                                        break;
     933                                                case 'a':
     934                                                        ExitFlag = 1;
     935                                                        if ((argptr >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr+1]))) {
     936                                                                ExitFlag = 255;
     937                                                                cerr << "Not enough or invalid arguments for adding atom: -a <element> <x> <y> <z>" << endl;
     938                                                        } else {
     939                                                                SaveFlag = true;
     940                                                                cout << Verbose(1) << "Adding new atom with element " << argv[argptr] << " at (" << argv[argptr+1] << "," << argv[argptr+2] << "," << argv[argptr+3] << "), ";
     941                                                                first = new atom;
     942                                                                first->type = periode->FindElement(atoi(argv[argptr]));
     943                                                                if (first->type != NULL)
     944                                                                        cout << Verbose(2) << "found element " << first->type->name << endl;
     945                                                                for (int i=NDIM;i--;)
     946                                                                        first->x.x[i] = atof(argv[argptr+1+i]);
     947                                                                if (first->type != NULL) {
     948                                                                        mol->AddAtom(first);    // add to molecule
     949                                                                        if ((config_present == empty) && (mol->AtomCount != 0))
     950                                                                                config_present = present;
     951                                                                } else
     952                                                                        cerr << Verbose(1) << "Could not find the specified element." << endl;
     953                                                                argptr+=4;
     954                                                        }
     955                                                        break;
     956                                                default:         // no match? Don't step on (this is done in next switch's default)
     957                                                        break;
     958                                        }
     959                                }
     960                                if (config_present == present) {
     961                                        switch(argv[argptr-1][1]) {
     962                                                case 'D':
     963                                                        ExitFlag = 1;
     964                                                        {
     965                                                                cout << Verbose(1) << "Depth-First-Search Analysis." << endl;
     966                                                                MoleculeLeafClass *Subgraphs = NULL;                    // list of subgraphs from DFS analysis
     967                                                                int *MinimumRingSize = new int[mol->AtomCount];
     968                                                                atom ***ListOfLocalAtoms = NULL;
     969                                                                int FragmentCounter = 0;
     970                                                                class StackClass<bond *> *BackEdgeStack = NULL;
     971                                                                class StackClass<bond *> *LocalBackEdgeStack = NULL;
     972                                                                mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr]), configuration.GetIsAngstroem());
     973                                                                mol->CreateListOfBondsPerAtom((ofstream *)&cout);
     974                                                                Subgraphs = mol->DepthFirstSearchAnalysis((ofstream *)&cout, BackEdgeStack);
     975                                                                if (Subgraphs != NULL) {
     976                                                                        Subgraphs->next->FillBondStructureFromReference((ofstream *)&cout, mol, (FragmentCounter = 0), ListOfLocalAtoms, false);        // we want to keep the created ListOfLocalAtoms
     977                                                                        while (Subgraphs->next != NULL) {
     978                                                                                Subgraphs = Subgraphs->next;
     979                                                                                LocalBackEdgeStack = new StackClass<bond *> (Subgraphs->Leaf->BondCount);
     980                                                                                Subgraphs->Leaf->PickLocalBackEdges((ofstream *)&cout, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack);
     981                                                                                Subgraphs->Leaf->CyclicStructureAnalysis((ofstream *)&cout, BackEdgeStack, MinimumRingSize);
     982                                                                                delete(LocalBackEdgeStack);
     983                                                                                delete(Subgraphs->previous);
     984                                                                        }
     985                                                                        delete(Subgraphs);
     986                                                                        for (int i=0;i<FragmentCounter;i++)
     987                                                                                Free((void **)&ListOfLocalAtoms[FragmentCounter], "ParseCommandLineOptions: **ListOfLocalAtoms[]");
     988                                                                        Free((void **)&ListOfLocalAtoms, "ParseCommandLineOptions: ***ListOfLocalAtoms");
     989                                                                }
     990                                                                delete(BackEdgeStack);
     991                                                                delete[](MinimumRingSize);
     992                                                        }
     993                                                        //argptr+=1;
     994                                                        break;
     995                                                case 'E':
     996                                                        ExitFlag = 1;
     997                                                        if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (argv[argptr+1][0] == '-')) {
     998                                                                ExitFlag = 255;
     999                                                                cerr << "Not enough or invalid arguments given for changing element: -E <atom nr.> <element>" << endl;
     1000                                                        } else {
     1001                                                                SaveFlag = true;
     1002                                                                cout << Verbose(1) << "Changing atom " << argv[argptr] << " to element " << argv[argptr+1] << "." << endl;
     1003                                                                first = mol->FindAtom(atoi(argv[argptr]));
     1004                                                                first->type = periode->FindElement(atoi(argv[argptr+1]));
     1005                                                                argptr+=2;
     1006                                                        }
     1007                                                        break;
     1008                                                case 'A':
     1009                                                        ExitFlag = 1;
     1010                                                        if ((argptr >= argc) || (argv[argptr][0] == '-')) {
     1011                                                                ExitFlag =255;
     1012                                                                cerr << "Missing source file for bonds in molecule: -A <bond sourcefile>" << endl;
     1013                                                        } else {
     1014                                                                cout << "Parsing bonds from " << argv[argptr] << "." << endl;
     1015                                                                ifstream *input = new ifstream(argv[argptr]);
     1016                                                                mol->CreateAdjacencyList2((ofstream *)&cout, input);
     1017                                                                input->close();
     1018                                                                argptr+=1;
     1019                                                        }
     1020                                                        break;
     1021                                                case 'N':
     1022                                                        ExitFlag = 1;
     1023                                                        if ((argptr+1 >= argc) || (argv[argptr+1][0] == '-')){
     1024                                                                ExitFlag = 255;
     1025                                                                cerr << "Not enough or invalid arguments given for non-convex envelope: -o <radius> <tecplot output file>" << endl;
     1026                                                        } else {
     1027                                                                class Tesselation T;
     1028                                                                int N = 15;
     1029                                                                int number = 100;
     1030                                                                string filename(argv[argptr+1]);
     1031                                                                filename.append(".csv");
     1032                                                                cout << Verbose(0) << "Evaluating non-convex envelope.";
     1033                                                                cout << Verbose(1) << "Using rolling ball of radius " << atof(argv[argptr]) << " and storing tecplot data in " << argv[argptr+1] << "." << endl;
     1034                                                                LinkedCell LCList(mol, atof(argv[argptr]));             // \NOTE not twice the radius??
     1035                                                                Find_non_convex_border((ofstream *)&cout, mol, &T, &LCList, argv[argptr+1], atof(argv[argptr]));
     1036                                                                FindDistributionOfEllipsoids((ofstream *)&cout, &T, &LCList, N, number, filename.c_str());
     1037                                                                argptr+=2;
     1038                                                        }
     1039                                                        break;
     1040                                                case 'T':
     1041                                                        ExitFlag = 1;
     1042                                                        if ((argptr >= argc) || (argv[argptr][0] == '-')) {
     1043                                                                ExitFlag = 255;
     1044                                                                cerr << "Not enough or invalid arguments given for storing tempature: -T <temperature file>" << endl;
     1045                                                        } else {
     1046                                                                cout << Verbose(1) << "Storing temperatures in " << argv[argptr] << "." << endl;
     1047                                                                ofstream *output = new ofstream(argv[argptr], ios::trunc);
     1048                                                                if (!mol->OutputTemperatureFromTrajectories((ofstream *)&cout, 0, mol->MDSteps, output))
     1049                                                                        cout << Verbose(2) << "File could not be written." << endl;
     1050                                                                else
     1051                                                                        cout << Verbose(2) << "File stored." << endl;
     1052                                                                output->close();
     1053                                                                delete(output);
     1054                                                                argptr+=1;
     1055                                                        }
     1056                                                        break;
     1057                                                case 'P':
     1058                                                        ExitFlag = 1;
     1059                                                        if ((argptr >= argc) || (argv[argptr][0] == '-')) {
     1060                                                                ExitFlag = 255;
     1061                                                                cerr << "Not enough or invalid arguments given for parsing and integrating forces: -P <forces file>" << endl;
     1062                                                        } else {
     1063                                                                SaveFlag = true;
     1064                                                                cout << Verbose(1) << "Parsing forces file and Verlet integrating." << endl;
     1065                                                                if (!mol->VerletForceIntegration(argv[argptr], configuration.Deltat, configuration.GetIsAngstroem()))
     1066                                                                        cout << Verbose(2) << "File not found." << endl;
     1067                                                                else
     1068                                                                        cout << Verbose(2) << "File found and parsed." << endl;
     1069                                                                argptr+=1;
     1070                                                        }
     1071                                                        break;
     1072                                                case 't':
     1073                                                        ExitFlag = 1;
     1074                                                        if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
     1075                                                                ExitFlag = 255;
     1076                                                                cerr << "Not enough or invalid arguments given for translation: -t <x> <y> <z>" << endl;
     1077                                                        } else {
     1078                                                                ExitFlag = 1;
     1079                                                                SaveFlag = true;
     1080                                                                cout << Verbose(1) << "Translating all ions to new origin." << endl;
     1081                                                                for (int i=NDIM;i--;)
     1082                                                                        x.x[i] = atof(argv[argptr+i]);
     1083                                                                mol->Translate((const Vector *)&x);
     1084                                                                argptr+=3;
     1085                                                        }
     1086                                                        break;
     1087                                                case 's':
     1088                                                        ExitFlag = 1;
     1089                                                        if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) {
     1090                                                                ExitFlag = 255;
     1091                                                                cerr << "Not enough or invalid arguments given for scaling: -s <factor/[factor_x]> [factor_y] [factor_z]" << endl;
     1092                                                        } else {
     1093                                                                SaveFlag = true;
     1094                                                                j = -1;
     1095                                                                cout << Verbose(1) << "Scaling all ion positions by factor." << endl;
     1096                                                                factor = new double[NDIM];
     1097                                                                factor[0] = atof(argv[argptr]);
     1098                                                                if ((argptr < argc) && (IsValidNumber(argv[argptr])))
     1099                                                                        argptr++;
     1100                                                                factor[1] = atof(argv[argptr]);
     1101                                                                if ((argptr < argc) && (IsValidNumber(argv[argptr])))
     1102                                                                        argptr++;
     1103                                                                factor[2] = atof(argv[argptr]);
     1104                                                                mol->Scale(&factor);
     1105                                                                for (int i=0;i<NDIM;i++) {
     1106                                                                        j += i+1;
     1107                                                                        x.x[i] = atof(argv[NDIM+i]);
     1108                                                                        mol->cell_size[j]*=factor[i];
     1109                                                                }
     1110                                                                delete[](factor);
     1111                                                                argptr+=1;
     1112                                                        }
     1113                                                        break;
     1114                                                case 'b':
     1115                                                        ExitFlag = 1;
     1116                                                        if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
     1117                                                                ExitFlag = 255;
     1118                                                                cerr << "Not enough or invalid arguments given for centering in box: -b <length_x> <length_y> <length_z>" << endl;
     1119                                                        } else {
     1120                                                                SaveFlag = true;
     1121                                                                j = -1;
     1122                                                                cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl;
     1123                                                                j=-1;
     1124                                                                for (int i=0;i<NDIM;i++) {
     1125                                                                        j += i+1;
     1126                                                                        x.x[i] = atof(argv[argptr++]);
     1127                                                                        mol->cell_size[j] += x.x[i]*2.;
     1128                                                                }
     1129                                                                // center
     1130                                                                mol->CenterInBox((ofstream *)&cout, &x);
     1131                                                                // update Box of atoms by boundary
     1132                                                                mol->SetBoxDimension(&x);
     1133                                                        }
     1134                                                        break;
     1135                                                case 'c':
     1136                                                        ExitFlag = 1;
     1137                                                        if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
     1138                                                                ExitFlag = 255;
     1139                                                                cerr << "Not enough or invalid arguments given for centering with boundary: -c <boundary_x> <boundary_y> <boundary_z>" << endl;
     1140                                                        } else {
     1141                                                                SaveFlag = true;
     1142                                                                j = -1;
     1143                                                                cout << Verbose(1) << "Centering atoms in config file within given additional boundary." << endl;
     1144                                                                // make every coordinate positive
     1145                                                                mol->CenterEdge((ofstream *)&cout, &x);
     1146                                                                // update Box of atoms by boundary
     1147                                                                mol->SetBoxDimension(&x);
     1148                                                                // translate each coordinate by boundary
     1149                                                                j=-1;
     1150                                                                for (int i=0;i<NDIM;i++) {
     1151                                                                        j += i+1;
     1152                                                                        x.x[i] = atof(argv[argptr++]);
     1153                                                                        mol->cell_size[j] += x.x[i]*2.;
     1154                                                                }
     1155                                                                mol->Translate((const Vector *)&x);
     1156                                                        }
     1157                                                        break;
     1158                                                case 'O':
     1159                                                        ExitFlag = 1;
     1160                                                        SaveFlag = true;
     1161                                                        cout << Verbose(1) << "Centering atoms in origin." << endl;
     1162                                                        mol->CenterOrigin((ofstream *)&cout, &x);
     1163                                                        mol->SetBoxDimension(&x);
     1164                                                        break;
     1165                                                case 'r':
     1166                                                        ExitFlag = 1;
     1167                                                        SaveFlag = true;
     1168                                                        cout << Verbose(1) << "Converting config file from supposed old to new syntax." << endl;
     1169                                                        break;
     1170                                                case 'F':
     1171                                                case 'f':
     1172                                                        ExitFlag = 1;
     1173                                                        if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1]))) {
     1174                                                                ExitFlag = 255;
     1175                                                                cerr << "Not enough or invalid arguments for fragmentation: -f <max. bond distance> <bond order>" << endl;
     1176                                                        } else {
     1177                                                                cout << "Fragmenting molecule with bond distance " << argv[argptr] << " angstroem, order of " << argv[argptr+1] << "." << endl;
     1178                                                                cout << Verbose(0) << "Creating connection matrix..." << endl;
     1179                                                                start = clock();
     1180                                                                mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr++]), configuration.GetIsAngstroem());
     1181                                                                cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl;
     1182                                                                if (mol->first->next != mol->last) {
     1183                                                                        ExitFlag = mol->FragmentMolecule((ofstream *)&cout, atoi(argv[argptr]), &configuration);
     1184                                                                }
     1185                                                                end = clock();
     1186                                                                cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
     1187                                                                argptr+=2;
     1188                                                        }
     1189                                                        break;
     1190                                                case 'm':
     1191                                                        ExitFlag = 1;
     1192                                                        j = atoi(argv[argptr++]);
     1193                                                        if ((j<0) || (j>1)) {
     1194                                                                cerr << Verbose(1) << "ERROR: Argument of '-m' should be either 0 for no-rotate or 1 for rotate." << endl;
     1195                                                                j = 0;
     1196                                                        }
     1197                                                        if (j) {
     1198                                                                SaveFlag = true;
     1199                                                                cout << Verbose(0) << "Converting to prinicipal axis system." << endl;
     1200                                                        } else
     1201                                                                cout << Verbose(0) << "Evaluating prinicipal axis." << endl;
     1202                                                        mol->PrincipalAxisSystem((ofstream *)&cout, (bool)j);
     1203                                                        break;
     1204                                                case 'o':
     1205                                                        ExitFlag = 1;
     1206                                                        if ((argptr >= argc) || (argv[argptr][0] == '-')){
     1207                                                                ExitFlag = 255;
     1208                                                                cerr << "Not enough or invalid arguments given for convex envelope: -o <tecplot output file>" << endl;
     1209                                                        } else {
     1210                                                                cout << Verbose(0) << "Evaluating volume of the convex envelope.";
     1211                                                                cout << Verbose(1) << "Storing tecplot data in " << argv[argptr] << "." << endl;
     1212                                                                VolumeOfConvexEnvelope((ofstream *)&cout, argv[argptr], &configuration, NULL, mol);
     1213                                                                argptr+=1;
     1214                                                        }
     1215                                                        break;
     1216                                                case 'U':
     1217                                                        ExitFlag = 1;
     1218                                                        if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) ) {
     1219                                                                ExitFlag = 255;
     1220                                                                cerr << "Not enough or invalid arguments given for suspension with specified volume: -U <volume> <density>" << endl;
     1221                                                                volume = -1; // for case 'u': don't print error again
     1222                                                        } else {
     1223                                                                volume = atof(argv[argptr++]);
     1224                                                                cout << Verbose(0) << "Using " << volume << " angstrom^3 as the volume instead of convex envelope one's." << endl;
     1225                                                        }
     1226                                                case 'u':
     1227                                                        ExitFlag = 1;
     1228                                                        if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) {
     1229                                                                if (volume != -1)
     1230                                                                        ExitFlag = 255;
     1231                                                                        cerr << "Not enough arguments given for suspension: -u <density>" << endl;
     1232                                                        } else {
     1233                                                                double density;
     1234                                                                SaveFlag = true;
     1235                                                                cout << Verbose(0) << "Evaluating necessary cell volume for a cluster suspended in water.";
     1236                                                                density = atof(argv[argptr++]);
     1237                                                                if (density < 1.0) {
     1238                                                                        cerr << Verbose(0) << "Density must be greater than 1.0g/cm^3 !" << endl;
     1239                                                                        density = 1.3;
     1240                                                                }
     1241//                                                              for(int i=0;i<NDIM;i++) {
     1242//                                                                      repetition[i] = atoi(argv[argptr++]);
     1243//                                                                      if (repetition[i] < 1)
     1244//                                                                              cerr << Verbose(0) << "ERROR: repetition value must be greater 1!" << endl;
     1245//                                                                      repetition[i] = 1;
     1246//                                                              }
     1247                                                                PrepareClustersinWater((ofstream *)&cout, &configuration, mol, volume, density);        // if volume == 0, will calculate from ConvexEnvelope
     1248                                                        }
     1249                                                        break;
     1250                                                case 'd':
     1251                                                        ExitFlag = 1;
     1252                                                        if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
     1253                                                                ExitFlag = 255;
     1254                                                                cerr << "Not enough or invalid arguments given for repeating cells: -d <repeat_x> <repeat_y> <repeat_z>" << endl;
     1255                                                        } else {
     1256                                                                SaveFlag = true;
     1257                                                                for (int axis = 1; axis <= NDIM; axis++) {
     1258                                                                        int faktor = atoi(argv[argptr++]);
     1259                                                                        int count;
     1260                                                                        element ** Elements;
     1261                                                                        Vector ** vectors;
     1262                                                                        if (faktor < 1) {
     1263                                                                                cerr << Verbose(0) << "ERROR: Repetition faktor mus be greater than 1!" << endl;
     1264                                                                                faktor = 1;
     1265                                                                        }
     1266                                                                        mol->CountAtoms((ofstream *)&cout);     // recount atoms
     1267                                                                        if (mol->AtomCount != 0) {      // if there is more than none
     1268                                                                                count = mol->AtomCount; // is changed becausing of adding, thus has to be stored away beforehand
     1269                                                                                Elements = new element *[count];
     1270                                                                                vectors = new Vector *[count];
     1271                                                                                j = 0;
     1272                                                                                first = mol->start;
     1273                                                                                while (first->next != mol->end) {       // make a list of all atoms with coordinates and element
     1274                                                                                        first = first->next;
     1275                                                                                        Elements[j] = first->type;
     1276                                                                                        vectors[j] = &first->x;
     1277                                                                                        j++;
     1278                                                                                }
     1279                                                                                if (count != j)
     1280                                                                                        cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl;
     1281                                                                                x.Zero();
     1282                                                                                y.Zero();
     1283                                                                                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
     1284                                                                                for (int i=1;i<faktor;i++) {    // then add this list with respective translation factor times
     1285                                                                                        x.AddVector(&y); // per factor one cell width further
     1286                                                                                        for (int k=count;k--;) { // go through every atom of the original cell
     1287                                                                                                first = new atom(); // create a new body
     1288                                                                                                first->x.CopyVector(vectors[k]);        // use coordinate of original atom
     1289                                                                                                first->x.AddVector(&x);                 // translate the coordinates
     1290                                                                                                first->type = Elements[k];      // insert original element
     1291                                                                                                mol->AddAtom(first);                            // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...)
     1292                                                                                        }
     1293                                                                                }
     1294                                                                                // free memory
     1295                                                                                delete[](Elements);
     1296                                                                                delete[](vectors);
     1297                                                                                // correct cell size
     1298                                                                                if (axis < 0) { // if sign was negative, we have to translate everything
     1299                                                                                        x.Zero();
     1300                                                                                        x.AddVector(&y);
     1301                                                                                        x.Scale(-(faktor-1));
     1302                                                                                        mol->Translate(&x);
     1303                                                                                }
     1304                                                                                mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor;
     1305                                                                        }
     1306                                                                }
     1307                                                        }
     1308                                                        break;
     1309                                                default:        // no match? Step on
     1310                                                        if ((argptr < argc) && (argv[argptr][0] != '-')) // if it started with a '-' we've already made a step!
     1311                                                                argptr++;
     1312                                                        break;
     1313                                        }
     1314                                }
     1315                        } else argptr++;
     1316                } while (argptr < argc);
     1317                if (SaveFlag)
     1318                        SaveConfig(ConfigFileName, &configuration, periode, mol);
     1319                if ((ExitFlag >= 1)) {
     1320                        delete(mol);
     1321                        delete(periode);
     1322                        return (ExitFlag);
     1323                }
     1324        } else {        // no arguments, hence scan the elements db
     1325                if (periode->LoadPeriodentafel(PathToDatabases))
     1326                        cout << Verbose(0) << "Element list loaded successfully." << endl;
     1327                else
     1328                        cout << Verbose(0) << "Element list loading failed." << endl;
     1329                configuration.RetrieveConfigPathAndName("main_pcp_linux");
     1330        }
     1331        return(0);
    13281332};
    13291333
     
    13321336int main(int argc, char **argv)
    13331337{
    1334   periodentafel *periode = new periodentafel; // and a period table of all elements
    1335   molecule *mol = new molecule(periode);    // first we need an empty molecule
    1336   config configuration;
    1337   double tmp1;
    1338   double bond, min_bond;
    1339   atom *first, *second;
    1340   char choice;  // menu choice char
    1341   Vector x,y,z,n;  // coordinates for absolute point in cell volume
     1338        periodentafel *periode = new periodentafel; // and a period table of all elements
     1339        molecule *mol = new molecule(periode);          // first we need an empty molecule
     1340        config configuration;
     1341        double tmp1;
     1342        double bond, min_bond;
     1343        atom *first, *second;
     1344        char choice;    // menu choice char
     1345        Vector x,y,z,n; // coordinates for absolute point in cell volume
    13421346        double *factor; // unit factor if desired
    1343   bool valid; // flag if input was valid or not
    1344   ifstream test;
    1345   ofstream output;
    1346   string line;
    1347   char filename[MAXSTRINGSIZE];
    1348   char *ConfigFileName = NULL;
    1349   char *ElementsFileName = NULL;
    1350   int Z;
    1351   int j, axis, count, faktor;
    1352   clock_t start,end;
    1353 //  int *MinimumRingSize = NULL;
    1354   MoleculeLeafClass *Subgraphs = NULL;
    1355 //  class StackClass<bond *> *BackEdgeStack = NULL;
    1356   element **Elements;
    1357   Vector **vectors;
    1358 
    1359   // =========================== PARSE COMMAND LINE OPTIONS ====================================
    1360   j = ParseCommandLineOptions(argc, argv, mol, periode, configuration, ConfigFileName, ElementsFileName);
    1361   if (j == 1) return 0; // just for -v and -h options
    1362   if (j) return j;  // something went wrong
    1363 
    1364   // General stuff
    1365   if (mol->cell_size[0] == 0.) {
    1366     cout << Verbose(0) << "enter lower triadiagonal form of basis matrix" << endl << endl;
    1367     for (int i=0;i<6;i++) {
    1368       cout << Verbose(1) << "Cell size" << i << ": ";
    1369       cin >> mol->cell_size[i];
    1370     }
    1371   }
    1372 
    1373   // =========================== START INTERACTIVE SESSION ====================================
    1374 
    1375   // now the main construction loop
    1376   cout << Verbose(0) << endl << "Now comes the real construction..." << endl;
    1377   do {
    1378     cout << Verbose(0) << endl << endl;
    1379     cout << Verbose(0) << "============Element list=======================" << endl;
    1380     mol->Checkout((ofstream *)&cout);
    1381     cout << Verbose(0) << "============Atom list==========================" << endl;
    1382     mol->Output((ofstream *)&cout);
    1383     cout << Verbose(0) << "============Menu===============================" << endl;
    1384     cout << Verbose(0) << "a - add an atom" << endl;
    1385     cout << Verbose(0) << "r - remove an atom" << endl;
    1386     cout << Verbose(0) << "b - scale a bond between atoms" << endl;
    1387     cout << Verbose(0) << "u - change an atoms element" << endl;
    1388     cout << Verbose(0) << "l - measure lengths, angles, ... for an atom" << endl;
    1389     cout << Verbose(0) << "-----------------------------------------------" << endl;
    1390     cout << Verbose(0) << "p - Parse xyz file" << endl;
    1391     cout << Verbose(0) << "e - edit the current configuration" << endl;
    1392     cout << Verbose(0) << "o - create connection matrix" << endl;
    1393     cout << Verbose(0) << "f - fragment molecule many-body bond order style" << endl;
    1394     cout << Verbose(0) << "-----------------------------------------------" << endl;
    1395     cout << Verbose(0) << "d - duplicate molecule/periodic cell" << endl;
    1396     cout << Verbose(0) << "i - realign molecule" << endl;
    1397     cout << Verbose(0) << "m - mirror all molecules" << endl;
    1398     cout << Verbose(0) << "t - translate molecule by vector" << endl;
    1399     cout << Verbose(0) << "c - scale by unit transformation" << endl;
    1400     cout << Verbose(0) << "g - center atoms in box" << endl;
    1401     cout << Verbose(0) << "-----------------------------------------------" << endl;
    1402     cout << Verbose(0) << "s - save current setup to config file" << endl;
    1403     cout << Verbose(0) << "T - call the current test routine" << endl;
    1404     cout << Verbose(0) << "q - quit" << endl;
    1405     cout << Verbose(0) << "===============================================" << endl;
    1406     cout << Verbose(0) << "Input: ";
    1407     cin >> choice;
    1408 
    1409     switch (choice) {
    1410       default:
    1411       case 'a': // add atom
    1412         AddAtoms(periode, mol);
    1413         choice = 'a';
    1414         break;
    1415 
    1416       case 'b': // scale a bond
    1417         cout << Verbose(0) << "Scaling bond length between two atoms." << endl;
    1418         first = mol->AskAtom("Enter first (fixed) atom: ");
    1419         second = mol->AskAtom("Enter second (shifting) atom: ");
    1420         min_bond = 0.;
    1421         for (int i=NDIM;i--;)
    1422           min_bond += (first->x.x[i]-second->x.x[i])*(first->x.x[i] - second->x.x[i]);
    1423         min_bond = sqrt(min_bond);
    1424         cout << Verbose(0) << "Current Bond length between " << first->type->name << " Atom " << first->nr << " and " << second->type->name << " Atom " << second->nr << ": " << min_bond << " a.u." << endl;
    1425         cout << Verbose(0) << "Enter new bond length [a.u.]: ";
    1426         cin >> bond;
    1427         for (int i=NDIM;i--;) {
    1428           second->x.x[i] -= (second->x.x[i]-first->x.x[i])/min_bond*(min_bond-bond);
    1429         }
    1430         //cout << Verbose(0) << "New coordinates of Atom " << second->nr << " are: ";
    1431         //second->Output(second->type->No, 1, (ofstream *)&cout);
    1432         break;
    1433 
    1434       case 'c': // unit scaling of the metric
    1435       cout << Verbose(0) << "Angstroem -> Bohrradius: 1.8897261\t\tBohrradius -> Angstroem: 0.52917721" << endl;
    1436       cout << Verbose(0) << "Enter three factors: ";
    1437       factor = new double[NDIM];
    1438       cin >> factor[0];
    1439       cin >> factor[1];
    1440       cin >> factor[2];
    1441       valid = true;
    1442       mol->Scale(&factor);
    1443       delete[](factor);
    1444       break;
    1445 
    1446       case 'd': // duplicate the periodic cell along a given axis, given times
    1447         cout << Verbose(0) << "State the axis [(+-)123]: ";
    1448         cin >> axis;
    1449         cout << Verbose(0) << "State the factor: ";
    1450         cin >> faktor;
    1451 
    1452         mol->CountAtoms((ofstream *)&cout);  // recount atoms
    1453         if (mol->AtomCount != 0) {  // if there is more than none
    1454           count = mol->AtomCount;  // is changed becausing of adding, thus has to be stored away beforehand
    1455           Elements = new element *[count];
    1456           vectors = new Vector *[count];
    1457           j = 0;
    1458           first = mol->start;
    1459           while (first->next != mol->end) {  // make a list of all atoms with coordinates and element
    1460             first = first->next;
    1461             Elements[j] = first->type;
    1462             vectors[j] = &first->x;
    1463             j++;
    1464           }
    1465           if (count != j)
    1466             cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl;
    1467           x.Zero();
    1468           y.Zero();
    1469           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
    1470           for (int i=1;i<faktor;i++) {  // then add this list with respective translation factor times
    1471             x.AddVector(&y); // per factor one cell width further
    1472             for (int k=count;k--;) { // go through every atom of the original cell
    1473               first = new atom(); // create a new body
    1474               first->x.CopyVector(vectors[k]);  // use coordinate of original atom
    1475               first->x.AddVector(&x);      // translate the coordinates
    1476               first->type = Elements[k];  // insert original element
    1477               mol->AddAtom(first);        // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...)
    1478             }
    1479           }
    1480           if (mol->first->next != mol->last) // if connect matrix is present already, redo it
    1481             mol->CreateAdjacencyList((ofstream *)&cout, mol->BondDistance, configuration.GetIsAngstroem());
    1482           // free memory
    1483           delete[](Elements);
    1484           delete[](vectors);
    1485           // correct cell size
    1486           if (axis < 0) { // if sign was negative, we have to translate everything
    1487             x.Zero();
    1488             x.AddVector(&y);
    1489             x.Scale(-(faktor-1));
    1490             mol->Translate(&x);
    1491           }
    1492           mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor;
    1493         }
    1494         break;
    1495 
    1496       case 'e': // edit each field of the configuration
    1497       configuration.Edit(mol);
    1498       break;
    1499 
    1500       case 'f':
    1501         FragmentAtoms(mol, &configuration);
    1502         break;
    1503 
    1504       case 'g': // center the atoms
    1505         CenterAtoms(mol);
    1506         break;
    1507 
    1508       case 'i': // align all atoms
    1509         AlignAtoms(periode, mol);
    1510         break;
    1511 
    1512       case 'l': // measure distances or angles
    1513         MeasureAtoms(periode, mol, &configuration);
    1514         break;
    1515 
    1516       case 'm': // mirror atoms along a given axis
    1517         MirrorAtoms(mol);
    1518         break;
    1519 
    1520       case 'o': // create the connection matrix
    1521         {
    1522           cout << Verbose(0) << "What's the maximum bond distance: ";
    1523           cin >> tmp1;
    1524           start = clock();
    1525           mol->CreateAdjacencyList((ofstream *)&cout, tmp1, configuration.GetIsAngstroem());
    1526           mol->CreateListOfBondsPerAtom((ofstream *)&cout);
    1527 //          Subgraphs = mol->DepthFirstSearchAnalysis((ofstream *)&cout, BackEdgeStack);
    1528 //          while (Subgraphs->next != NULL) {
    1529 //            Subgraphs = Subgraphs->next;
    1530 //            Subgraphs->Leaf->CyclicStructureAnalysis((ofstream *)&cout, BackEdgeStack, MinimumRingSize);
    1531 //            delete(Subgraphs->previous);
    1532 //          }
    1533 //          delete(Subgraphs);    // we don't need the list here, so free everything
    1534 //          delete[](MinimumRingSize);
    1535 //          Subgraphs = NULL;
    1536           end = clock();
    1537           cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
    1538         }
    1539         break;
    1540 
    1541       case 'p': // parse and XYZ file
    1542         cout << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl;
    1543         do {
    1544           cout << Verbose(0) << "Enter file name: ";
    1545           cin >> filename;
    1546         } while (!mol->AddXYZFile(filename));
    1547         break;
    1548 
    1549       case 'q': // quit
    1550         break;
    1551 
    1552       case 'r': // remove atom
    1553         RemoveAtoms(mol);
    1554         break;
    1555 
    1556       case 's': // save to config file
    1557         SaveConfig(ConfigFileName, &configuration, periode, mol);
    1558         break;
    1559 
    1560       case 't': // translate all atoms
    1561       cout << Verbose(0) << "Enter translation vector." << endl;
    1562       x.AskPosition(mol->cell_size,0);
    1563       mol->Translate((const Vector *)&x);
    1564       break;
    1565 
    1566       case 'T':
    1567         testroutine(mol);
    1568         break;
    1569 
    1570       case 'u': // change an atom's element
    1571         first = NULL;
    1572         do {
    1573           cout << Verbose(0) << "Change the element of which atom: ";
    1574           cin >> Z;
    1575         } while ((first = mol->FindAtom(Z)) == NULL);
    1576         cout << Verbose(0) << "New element by atomic number Z: ";
    1577         cin >> Z;
    1578         first->type = periode->FindElement(Z);
    1579         cout << Verbose(0) << "Atom " << first->nr << "'s element is " << first->type->name << "." << endl;
    1580         break;
    1581     };
    1582   } while (choice != 'q');
    1583 
    1584   // save element data base
    1585   if (periode->StorePeriodentafel(ElementsFileName)) //ElementsFileName
    1586     cout << Verbose(0) << "Saving of elements.db successful." << endl;
    1587   else
    1588     cout << Verbose(0) << "Saving of elements.db failed." << endl;
    1589 
    1590   // Free all
    1591   if (Subgraphs != NULL) {  // free disconnected subgraph list of DFS analysis was performed
    1592     while (Subgraphs->next != NULL) {
    1593       Subgraphs = Subgraphs->next;
    1594       delete(Subgraphs->previous);
    1595     }
    1596     delete(Subgraphs);
    1597   }
    1598   delete(mol);
    1599   delete(periode);
    1600   return (0);
     1347        bool valid; // flag if input was valid or not
     1348        ifstream test;
     1349        ofstream output;
     1350        string line;
     1351        char filename[MAXSTRINGSIZE];
     1352        char *ConfigFileName = NULL;
     1353        char *ElementsFileName = NULL;
     1354        int Z;
     1355        int j, axis, count, faktor;
     1356        clock_t start,end;
     1357//      int *MinimumRingSize = NULL;
     1358        MoleculeLeafClass *Subgraphs = NULL;
     1359//      class StackClass<bond *> *BackEdgeStack = NULL;
     1360        element **Elements;
     1361        Vector **vectors;
     1362
     1363        // =========================== PARSE COMMAND LINE OPTIONS ====================================
     1364        j = ParseCommandLineOptions(argc, argv, mol, periode, configuration, ConfigFileName, ElementsFileName);
     1365        if (j == 1) return 0; // just for -v and -h options
     1366        if (j) return j;        // something went wrong
     1367
     1368        // General stuff
     1369        if (mol->cell_size[0] == 0.) {
     1370                cout << Verbose(0) << "enter lower triadiagonal form of basis matrix" << endl << endl;
     1371                for (int i=0;i<6;i++) {
     1372                        cout << Verbose(1) << "Cell size" << i << ": ";
     1373                        cin >> mol->cell_size[i];
     1374                }
     1375        }
     1376
     1377        // =========================== START INTERACTIVE SESSION ====================================
     1378
     1379        // now the main construction loop
     1380        cout << Verbose(0) << endl << "Now comes the real construction..." << endl;
     1381        do {
     1382                cout << Verbose(0) << endl << endl;
     1383                cout << Verbose(0) << "============Element list=======================" << endl;
     1384                mol->Checkout((ofstream *)&cout);
     1385                cout << Verbose(0) << "============Atom list==========================" << endl;
     1386                mol->Output((ofstream *)&cout);
     1387                cout << Verbose(0) << "============Menu===============================" << endl;
     1388                cout << Verbose(0) << "a - add an atom" << endl;
     1389                cout << Verbose(0) << "r - remove an atom" << endl;
     1390                cout << Verbose(0) << "b - scale a bond between atoms" << endl;
     1391                cout << Verbose(0) << "u - change an atoms element" << endl;
     1392                cout << Verbose(0) << "l - measure lengths, angles, ... for an atom" << endl;
     1393                cout << Verbose(0) << "-----------------------------------------------" << endl;
     1394                cout << Verbose(0) << "p - Parse xyz file" << endl;
     1395                cout << Verbose(0) << "e - edit the current configuration" << endl;
     1396                cout << Verbose(0) << "o - create connection matrix" << endl;
     1397                cout << Verbose(0) << "f - fragment molecule many-body bond order style" << endl;
     1398                cout << Verbose(0) << "-----------------------------------------------" << endl;
     1399                cout << Verbose(0) << "d - duplicate molecule/periodic cell" << endl;
     1400                cout << Verbose(0) << "i - realign molecule" << endl;
     1401                cout << Verbose(0) << "m - mirror all molecules" << endl;
     1402                cout << Verbose(0) << "t - translate molecule by vector" << endl;
     1403                cout << Verbose(0) << "c - scale by unit transformation" << endl;
     1404                cout << Verbose(0) << "g - center atoms in box" << endl;
     1405                cout << Verbose(0) << "-----------------------------------------------" << endl;
     1406                cout << Verbose(0) << "s - save current setup to config file" << endl;
     1407                cout << Verbose(0) << "T - call the current test routine" << endl;
     1408                cout << Verbose(0) << "q - quit" << endl;
     1409                cout << Verbose(0) << "===============================================" << endl;
     1410                cout << Verbose(0) << "Input: ";
     1411                cin >> choice;
     1412
     1413                switch (choice) {
     1414                        default:
     1415                        case 'a': // add atom
     1416                                AddAtoms(periode, mol);
     1417                                choice = 'a';
     1418                                break;
     1419
     1420                        case 'b': // scale a bond
     1421                                cout << Verbose(0) << "Scaling bond length between two atoms." << endl;
     1422                                first = mol->AskAtom("Enter first (fixed) atom: ");
     1423                                second = mol->AskAtom("Enter second (shifting) atom: ");
     1424                                min_bond = 0.;
     1425                                for (int i=NDIM;i--;)
     1426                                        min_bond += (first->x.x[i]-second->x.x[i])*(first->x.x[i] - second->x.x[i]);
     1427                                min_bond = sqrt(min_bond);
     1428                                cout << Verbose(0) << "Current Bond length between " << first->type->name << " Atom " << first->nr << " and " << second->type->name << " Atom " << second->nr << ": " << min_bond << " a.u." << endl;
     1429                                cout << Verbose(0) << "Enter new bond length [a.u.]: ";
     1430                                cin >> bond;
     1431                                for (int i=NDIM;i--;) {
     1432                                        second->x.x[i] -= (second->x.x[i]-first->x.x[i])/min_bond*(min_bond-bond);
     1433                                }
     1434                                //cout << Verbose(0) << "New coordinates of Atom " << second->nr << " are: ";
     1435                                //second->Output(second->type->No, 1, (ofstream *)&cout);
     1436                                break;
     1437
     1438                        case 'c': // unit scaling of the metric
     1439                        cout << Verbose(0) << "Angstroem -> Bohrradius: 1.8897261\t\tBohrradius -> Angstroem: 0.52917721" << endl;
     1440                        cout << Verbose(0) << "Enter three factors: ";
     1441                        factor = new double[NDIM];
     1442                        cin >> factor[0];
     1443                        cin >> factor[1];
     1444                        cin >> factor[2];
     1445                        valid = true;
     1446                        mol->Scale(&factor);
     1447                        delete[](factor);
     1448                        break;
     1449
     1450                        case 'd': // duplicate the periodic cell along a given axis, given times
     1451                                cout << Verbose(0) << "State the axis [(+-)123]: ";
     1452                                cin >> axis;
     1453                                cout << Verbose(0) << "State the factor: ";
     1454                                cin >> faktor;
     1455
     1456                                mol->CountAtoms((ofstream *)&cout);     // recount atoms
     1457                                if (mol->AtomCount != 0) {      // if there is more than none
     1458                                        count = mol->AtomCount; // is changed becausing of adding, thus has to be stored away beforehand
     1459                                        Elements = new element *[count];
     1460                                        vectors = new Vector *[count];
     1461                                        j = 0;
     1462                                        first = mol->start;
     1463                                        while (first->next != mol->end) {       // make a list of all atoms with coordinates and element
     1464                                                first = first->next;
     1465                                                Elements[j] = first->type;
     1466                                                vectors[j] = &first->x;
     1467                                                j++;
     1468                                        }
     1469                                        if (count != j)
     1470                                                cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl;
     1471                                        x.Zero();
     1472                                        y.Zero();
     1473                                        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
     1474                                        for (int i=1;i<faktor;i++) {    // then add this list with respective translation factor times
     1475                                                x.AddVector(&y); // per factor one cell width further
     1476                                                for (int k=count;k--;) { // go through every atom of the original cell
     1477                                                        first = new atom(); // create a new body
     1478                                                        first->x.CopyVector(vectors[k]);        // use coordinate of original atom
     1479                                                        first->x.AddVector(&x);                 // translate the coordinates
     1480                                                        first->type = Elements[k];      // insert original element
     1481                                                        mol->AddAtom(first);                            // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...)
     1482                                                }
     1483                                        }
     1484                                        if (mol->first->next != mol->last) // if connect matrix is present already, redo it
     1485                                                mol->CreateAdjacencyList((ofstream *)&cout, mol->BondDistance, configuration.GetIsAngstroem());
     1486                                        // free memory
     1487                                        delete[](Elements);
     1488                                        delete[](vectors);
     1489                                        // correct cell size
     1490                                        if (axis < 0) { // if sign was negative, we have to translate everything
     1491                                                x.Zero();
     1492                                                x.AddVector(&y);
     1493                                                x.Scale(-(faktor-1));
     1494                                                mol->Translate(&x);
     1495                                        }
     1496                                        mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor;
     1497                                }
     1498                                break;
     1499
     1500                        case 'e': // edit each field of the configuration
     1501                        configuration.Edit(mol);
     1502                        break;
     1503
     1504                        case 'f':
     1505                                FragmentAtoms(mol, &configuration);
     1506                                break;
     1507
     1508                        case 'g': // center the atoms
     1509                                CenterAtoms(mol);
     1510                                break;
     1511
     1512                        case 'i': // align all atoms
     1513                                AlignAtoms(periode, mol);
     1514                                break;
     1515
     1516                        case 'l': // measure distances or angles
     1517                                MeasureAtoms(periode, mol, &configuration);
     1518                                break;
     1519
     1520                        case 'm': // mirror atoms along a given axis
     1521                                MirrorAtoms(mol);
     1522                                break;
     1523
     1524                        case 'o': // create the connection matrix
     1525                                {
     1526                                        cout << Verbose(0) << "What's the maximum bond distance: ";
     1527                                        cin >> tmp1;
     1528                                        start = clock();
     1529                                        mol->CreateAdjacencyList((ofstream *)&cout, tmp1, configuration.GetIsAngstroem());
     1530                                        mol->CreateListOfBondsPerAtom((ofstream *)&cout);
     1531//                                      Subgraphs = mol->DepthFirstSearchAnalysis((ofstream *)&cout, BackEdgeStack);
     1532//                                      while (Subgraphs->next != NULL) {
     1533//                                              Subgraphs = Subgraphs->next;
     1534//                                              Subgraphs->Leaf->CyclicStructureAnalysis((ofstream *)&cout, BackEdgeStack, MinimumRingSize);
     1535//                                              delete(Subgraphs->previous);
     1536//                                      }
     1537//                                      delete(Subgraphs);              // we don't need the list here, so free everything
     1538//                                      delete[](MinimumRingSize);
     1539//                                      Subgraphs = NULL;
     1540                                        end = clock();
     1541                                        cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
     1542                                }
     1543                                break;
     1544
     1545                        case 'p': // parse and XYZ file
     1546                                cout << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl;
     1547                                do {
     1548                                        cout << Verbose(0) << "Enter file name: ";
     1549                                        cin >> filename;
     1550                                } while (!mol->AddXYZFile(filename));
     1551                                break;
     1552
     1553                        case 'q': // quit
     1554                                break;
     1555
     1556                        case 'r': // remove atom
     1557                                RemoveAtoms(mol);
     1558                                break;
     1559
     1560                        case 's': // save to config file
     1561                                SaveConfig(ConfigFileName, &configuration, periode, mol);
     1562                                break;
     1563
     1564                        case 't': // translate all atoms
     1565                        cout << Verbose(0) << "Enter translation vector." << endl;
     1566                        x.AskPosition(mol->cell_size,0);
     1567                        mol->Translate((const Vector *)&x);
     1568                        break;
     1569
     1570                        case 'T':
     1571                                testroutine(mol);
     1572                                break;
     1573
     1574                        case 'u': // change an atom's element
     1575                                first = NULL;
     1576                                do {
     1577                                        cout << Verbose(0) << "Change the element of which atom: ";
     1578                                        cin >> Z;
     1579                                } while ((first = mol->FindAtom(Z)) == NULL);
     1580                                cout << Verbose(0) << "New element by atomic number Z: ";
     1581                                cin >> Z;
     1582                                first->type = periode->FindElement(Z);
     1583                                cout << Verbose(0) << "Atom " << first->nr << "'s element is " << first->type->name << "." << endl;
     1584                                break;
     1585                };
     1586        } while (choice != 'q');
     1587
     1588        // save element data base
     1589        if (periode->StorePeriodentafel(ElementsFileName)) //ElementsFileName
     1590                cout << Verbose(0) << "Saving of elements.db successful." << endl;
     1591        else
     1592                cout << Verbose(0) << "Saving of elements.db failed." << endl;
     1593
     1594        // Free all
     1595        if (Subgraphs != NULL) {        // free disconnected subgraph list of DFS analysis was performed
     1596                while (Subgraphs->next != NULL) {
     1597                        Subgraphs = Subgraphs->next;
     1598                        delete(Subgraphs->previous);
     1599                }
     1600                delete(Subgraphs);
     1601        }
     1602        delete(mol);
     1603        delete(periode);
     1604        return (0);
    16011605}
    16021606
  • src/config.cpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    1313config::config()
    1414{
    15   mainname = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname");
    16   defaultpath = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname");
    17   pseudopotpath = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname");
    18   configpath = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname");
    19   configname = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname");
    20   strcpy(mainname,"pcp");
    21   strcpy(defaultpath,"not specified");
    22   strcpy(pseudopotpath,"not specified");
    23   configpath[0]='\0';
    24   configname[0]='\0';
    25  
    26   FastParsing = false;
    27   ProcPEGamma=8;
    28   ProcPEPsi=1;
    29   DoOutVis=0;
    30   DoOutMes=1;
    31   DoOutNICS=0;
    32   DoOutOrbitals=0;
    33   DoOutCurrent=0;
    34   DoPerturbation=0;
    35   DoFullCurrent=0;
    36   DoWannier=0;
    37   CommonWannier=0;
    38   SawtoothStart=0.01;
    39   VectorPlane=0;
    40   VectorCut=0;
    41   UseAddGramSch=1;
    42   Seed=1;
    43  
    44   MaxOuterStep=0;
    45   Deltat=1;
    46   OutVisStep=10;
    47   OutSrcStep=5;
    48   TargetTemp=0.00095004455;
    49   ScaleTempStep=25;
    50   MaxPsiStep=0;
    51   EpsWannier=1e-7;
    52  
    53   MaxMinStep=100;
    54   RelEpsTotalEnergy=1e-7;
    55   RelEpsKineticEnergy=1e-5;
    56   MaxMinStopStep=1;
    57   MaxMinGapStopStep=0;
    58   MaxInitMinStep=100;
    59   InitRelEpsTotalEnergy=1e-5;
    60   InitRelEpsKineticEnergy=1e-4;
    61   InitMaxMinStopStep=1;
    62   InitMaxMinGapStopStep=0;
    63  
    64   //BoxLength[NDIM*NDIM];
    65  
    66   ECut=128.;
    67   MaxLevel=5;
    68   RiemannTensor=0;
    69   LevRFactor=0;
    70   RiemannLevel=0;
    71   Lev0Factor=2;
    72   RTActualUse=0;
    73   PsiType=0;
    74   MaxPsiDouble=0;
    75   PsiMaxNoUp=0;
    76   PsiMaxNoDown=0;
    77   AddPsis=0;
    78  
    79   RCut=20.;
    80   StructOpt=0;
    81   IsAngstroem=1;
    82   RelativeCoord=0;
    83   MaxTypes=0;
     15        mainname = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname");
     16        defaultpath = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname");
     17        pseudopotpath = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname");
     18        configpath = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname");
     19        configname = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname");
     20        strcpy(mainname,"pcp");
     21        strcpy(defaultpath,"not specified");
     22        strcpy(pseudopotpath,"not specified");
     23        configpath[0]='\0';
     24        configname[0]='\0';
     25       
     26        FastParsing = false;
     27        ProcPEGamma=8;
     28        ProcPEPsi=1;
     29        DoOutVis=0;
     30        DoOutMes=1;
     31        DoOutNICS=0;
     32        DoOutOrbitals=0;
     33        DoOutCurrent=0;
     34        DoPerturbation=0;
     35        DoFullCurrent=0;
     36        DoWannier=0;
     37        CommonWannier=0;
     38        SawtoothStart=0.01;
     39        VectorPlane=0;
     40        VectorCut=0;
     41        UseAddGramSch=1;
     42        Seed=1;
     43       
     44        MaxOuterStep=0;
     45        Deltat=1;
     46        OutVisStep=10;
     47        OutSrcStep=5;
     48        TargetTemp=0.00095004455;
     49        ScaleTempStep=25;
     50        MaxPsiStep=0;
     51        EpsWannier=1e-7;
     52       
     53        MaxMinStep=100;
     54        RelEpsTotalEnergy=1e-7;
     55        RelEpsKineticEnergy=1e-5;
     56        MaxMinStopStep=1;
     57        MaxMinGapStopStep=0;
     58        MaxInitMinStep=100;
     59        InitRelEpsTotalEnergy=1e-5;
     60        InitRelEpsKineticEnergy=1e-4;
     61        InitMaxMinStopStep=1;
     62        InitMaxMinGapStopStep=0;
     63       
     64        //BoxLength[NDIM*NDIM];
     65       
     66        ECut=128.;
     67        MaxLevel=5;
     68        RiemannTensor=0;
     69        LevRFactor=0;
     70        RiemannLevel=0;
     71        Lev0Factor=2;
     72        RTActualUse=0;
     73        PsiType=0;
     74        MaxPsiDouble=0;
     75        PsiMaxNoUp=0;
     76        PsiMaxNoDown=0;
     77        AddPsis=0;
     78       
     79        RCut=20.;
     80        StructOpt=0;
     81        IsAngstroem=1;
     82        RelativeCoord=0;
     83        MaxTypes=0;
    8484};
    8585
     
    8989config::~config()
    9090{
    91   Free((void **)&mainname, "config::~config: *mainname");
    92   Free((void **)&defaultpath, "config::~config: *defaultpath");
    93   Free((void **)&pseudopotpath, "config::~config: *pseudopotpath");
    94   Free((void **)&configpath, "config::~config: *configpath");
    95   Free((void **)&configname, "config::~config: *configname");
     91        Free((void **)&mainname, "config::~config: *mainname");
     92        Free((void **)&defaultpath, "config::~config: *defaultpath");
     93        Free((void **)&pseudopotpath, "config::~config: *pseudopotpath");
     94        Free((void **)&configpath, "config::~config: *configpath");
     95        Free((void **)&configname, "config::~config: *configname");
    9696};
    9797
     
    102102void config::Edit(molecule *mol)
    103103{
    104   char choice;
    105  
    106   do {
    107     cout << Verbose(0) << "===========EDIT CONFIGURATION============================" << endl;
    108     cout << Verbose(0) << " A - mainname (prefix for all runtime files)" << endl;
    109     cout << Verbose(0) << " B - Default path (for runtime files)" << endl;
    110     cout << Verbose(0) << " C - Path of pseudopotential files" << endl;
    111     cout << Verbose(0) << " D - Number of coefficient sharing processes" << endl;
    112     cout << Verbose(0) << " E - Number of wave function sharing processes" << endl;
    113     cout << Verbose(0) << " F - 0: Don't output density for OpenDX, 1: do" << endl;
    114     cout << Verbose(0) << " G - 0: Don't output physical data, 1: do" << endl;
    115     cout << Verbose(0) << " H - 0: Don't output densities of each unperturbed orbital for OpenDX, 1: do" << endl;
    116     cout << Verbose(0) << " I - 0: Don't output current density for OpenDX, 1: do" << endl;
    117     cout << Verbose(0) << " J - 0: Don't do the full current calculation, 1: do" << endl;
    118     cout << Verbose(0) << " K - 0: Don't do perturbation calculation to obtain susceptibility and shielding, 1: do" << endl;
    119     cout << Verbose(0) << " L - 0: Wannier centres as calculated, 1: common centre for all, 2: unite centres according to spread, 3: cell centre, 4: shifted to nearest grid point" << endl;
    120     cout << Verbose(0) << " M - Absolute begin of unphysical sawtooth transfer for position operator within cell" << endl;
    121     cout << Verbose(0) << " N - (0,1,2) x,y,z-plane to do two-dimensional current vector cut" << endl;
    122     cout << Verbose(0) << " O - Absolute position along vector cut axis for cut plane" << endl;
    123     cout << Verbose(0) << " P - Additional Gram-Schmidt-Orthonormalization to stabilize numerics" << endl;
    124     cout << Verbose(0) << " Q - Initial integer value of random number generator" << endl;
    125     cout << Verbose(0) << " R - for perturbation 0, for structure optimization defines upper limit of iterations" << endl;
    126     cout << Verbose(0) << " T - Output visual after ...th step" << endl;
    127     cout << Verbose(0) << " U - Output source densities of wave functions after ...th step" << endl;
    128     cout << Verbose(0) << " X - minimization iterations per wave function, if unsure leave at default value 0" << endl;
    129     cout << Verbose(0) << " Y - tolerance value for total spread in iterative Jacobi diagonalization" << endl;
    130     cout << Verbose(0) << " Z - Maximum number of minimization iterations" << endl;
    131     cout << Verbose(0) << " a - Relative change in total energy to stop min. iteration" << endl;
    132     cout << Verbose(0) << " b - Relative change in kinetic energy to stop min. iteration" << endl;
    133     cout << Verbose(0) << " c - Check stop conditions every ..th step during min. iteration" << endl;
    134     cout << Verbose(0) << " e - Maximum number of minimization iterations during initial level" << endl;
    135     cout << Verbose(0) << " f - Relative change in total energy to stop min. iteration during initial level" << endl;
    136     cout << Verbose(0) << " g - Relative change in kinetic energy to stop min. iteration during initial level" << endl;
    137     cout << Verbose(0) << " h - Check stop conditions every ..th step during min. iteration during initial level" << endl;
    138     cout << Verbose(0) << " j - six lower diagonal entries of matrix, defining the unit cell" << endl;
    139     cout << Verbose(0) << " k - Energy cutoff of plane wave basis in Hartree" << endl;
    140     cout << Verbose(0) << " l - Maximum number of levels in multi-level-ansatz" << endl;
    141     cout << Verbose(0) << " m - Factor by which grid nodes increase between standard and upper level" << endl;
    142     cout << Verbose(0) << " n - 0: Don't use RiemannTensor, 1: Do" << endl;
    143     cout << Verbose(0) << " o - Factor by which grid nodes increase between Riemann and standard(?) level" << endl;
    144     cout << Verbose(0) << " p - Number of Riemann levels" << endl;
    145     cout << Verbose(0) << " r - 0: Don't Use RiemannTensor, 1: Do" << endl;
    146     cout << Verbose(0) << " s - 0: Doubly occupied orbitals, 1: Up-/Down-Orbitals" << endl;
    147     cout << Verbose(0) << " t - Number of orbitals (depends pn SpinType)" << endl;
    148     cout << Verbose(0) << " u - Number of SpinUp orbitals (depends on SpinType)" << endl;
    149     cout << Verbose(0) << " v - Number of SpinDown orbitals (depends on SpinType)" << endl;
    150     cout << Verbose(0) << " w - Number of additional, unoccupied orbitals" << endl;
    151     cout << Verbose(0) << " x - radial cutoff for ewald summation in Bohrradii" << endl;
    152     cout << Verbose(0) << " y - 0: Don't do structure optimization beforehand, 1: Do" << endl;
    153     cout << Verbose(0) << " z - 0: Units are in Bohr radii, 1: units are in Aengstrom" << endl;
    154     cout << Verbose(0) << " i - 0: Coordinates given in file are absolute, 1: ... are relative to unit cell" << endl;
    155     cout << Verbose(0) << "=========================================================" << endl;
    156     cout << Verbose(0) << "INPUT: ";
    157     cin >> choice;
    158    
    159     switch (choice) {
    160         case 'A': // mainname
    161           cout << Verbose(0) << "Old: " << config::mainname << "\t new: ";
    162           cin >> config::mainname;
    163           break;
    164         case 'B': // defaultpath
    165           cout << Verbose(0) << "Old: " << config::defaultpath << "\t new: ";
    166           cin >> config::defaultpath;
    167           break;
    168         case 'C': // pseudopotpath
    169           cout << Verbose(0) << "Old: " << config::pseudopotpath << "\t new: ";
    170           cin >> config::pseudopotpath;
    171           break;
    172 
    173         case 'D': // ProcPEGamma
    174           cout << Verbose(0) << "Old: " << config::ProcPEGamma << "\t new: ";
    175           cin >> config::ProcPEGamma;
    176           break;
    177         case 'E': // ProcPEPsi
    178           cout << Verbose(0) << "Old: " << config::ProcPEPsi << "\t new: ";
    179           cin >> config::ProcPEPsi;
    180           break;
    181         case 'F': // DoOutVis
    182           cout << Verbose(0) << "Old: " << config::DoOutVis << "\t new: ";
    183           cin >> config::DoOutVis;
    184           break;
    185         case 'G': // DoOutMes
    186           cout << Verbose(0) << "Old: " << config::DoOutMes << "\t new: ";
    187           cin >> config::DoOutMes;
    188           break;
    189         case 'H': // DoOutOrbitals
    190           cout << Verbose(0) << "Old: " << config::DoOutOrbitals << "\t new: ";
    191           cin >> config::DoOutOrbitals;
    192           break;
    193         case 'I': // DoOutCurrent
    194           cout << Verbose(0) << "Old: " << config::DoOutCurrent << "\t new: ";
    195           cin >> config::DoOutCurrent;
    196           break;
    197         case 'J': // DoFullCurrent
    198           cout << Verbose(0) << "Old: " << config::DoFullCurrent << "\t new: ";
    199           cin >> config::DoFullCurrent;
    200           break;
    201         case 'K': // DoPerturbation
    202           cout << Verbose(0) << "Old: " << config::DoPerturbation << "\t new: ";
    203           cin >> config::DoPerturbation;
    204           break;
    205         case 'L': // CommonWannier
    206           cout << Verbose(0) << "Old: " << config::CommonWannier << "\t new: ";
    207           cin >> config::CommonWannier;
    208           break;
    209         case 'M': // SawtoothStart
    210           cout << Verbose(0) << "Old: " << config::SawtoothStart << "\t new: ";
    211           cin >> config::SawtoothStart;
    212           break;
    213         case 'N': // VectorPlane
    214           cout << Verbose(0) << "Old: " << config::VectorPlane << "\t new: ";
    215           cin >> config::VectorPlane;
    216           break;
    217         case 'O': // VectorCut
    218           cout << Verbose(0) << "Old: " << config::VectorCut << "\t new: ";
    219           cin >> config::VectorCut;
    220           break;
    221         case 'P': // UseAddGramSch
    222           cout << Verbose(0) << "Old: " << config::UseAddGramSch << "\t new: ";
    223           cin >> config::UseAddGramSch;
    224           break;
    225         case 'Q': // Seed
    226           cout << Verbose(0) << "Old: " << config::Seed << "\t new: ";
    227           cin >> config::Seed;
    228           break;
    229 
    230         case 'R': // MaxOuterStep
    231           cout << Verbose(0) << "Old: " << config::MaxOuterStep << "\t new: ";
    232           cin >> config::MaxOuterStep;
    233           break;
    234         case 'T': // OutVisStep
    235           cout << Verbose(0) << "Old: " << config::OutVisStep << "\t new: ";
    236           cin >> config::OutVisStep;
    237           break;
    238         case 'U': // OutSrcStep
    239           cout << Verbose(0) << "Old: " << config::OutSrcStep << "\t new: ";
    240           cin >> config::OutSrcStep;
    241           break;
    242         case 'X': // MaxPsiStep
    243           cout << Verbose(0) << "Old: " << config::MaxPsiStep << "\t new: ";
    244           cin >> config::MaxPsiStep;
    245           break;
    246         case 'Y': // EpsWannier
    247           cout << Verbose(0) << "Old: " << config::EpsWannier << "\t new: ";
    248           cin >> config::EpsWannier;
    249           break;
    250 
    251         case 'Z': // MaxMinStep
    252           cout << Verbose(0) << "Old: " << config::MaxMinStep << "\t new: ";
    253           cin >> config::MaxMinStep;
    254           break;
    255         case 'a': // RelEpsTotalEnergy
    256           cout << Verbose(0) << "Old: " << config::RelEpsTotalEnergy << "\t new: ";
    257           cin >> config::RelEpsTotalEnergy;
    258           break;
    259         case 'b': // RelEpsKineticEnergy
    260           cout << Verbose(0) << "Old: " << config::RelEpsKineticEnergy << "\t new: ";
    261           cin >> config::RelEpsKineticEnergy;
    262           break;
    263         case 'c': // MaxMinStopStep
    264           cout << Verbose(0) << "Old: " << config::MaxMinStopStep << "\t new: ";
    265           cin >> config::MaxMinStopStep;
    266           break;
    267         case 'e': // MaxInitMinStep
    268           cout << Verbose(0) << "Old: " << config::MaxInitMinStep << "\t new: ";
    269           cin >> config::MaxInitMinStep;
    270           break;
    271         case 'f': // InitRelEpsTotalEnergy
    272           cout << Verbose(0) << "Old: " << config::InitRelEpsTotalEnergy << "\t new: ";
    273           cin >> config::InitRelEpsTotalEnergy;
    274           break;
    275         case 'g': // InitRelEpsKineticEnergy
    276           cout << Verbose(0) << "Old: " << config::InitRelEpsKineticEnergy << "\t new: ";
    277           cin >> config::InitRelEpsKineticEnergy;
    278           break;
    279         case 'h': // InitMaxMinStopStep
    280           cout << Verbose(0) << "Old: " << config::InitMaxMinStopStep << "\t new: ";
    281           cin >> config::InitMaxMinStopStep;
    282           break;
    283        
    284         case 'j': // BoxLength
    285           cout << Verbose(0) << "enter lower triadiagonalo form of basis matrix" << endl << endl;
    286           for (int i=0;i<6;i++) {
    287             cout << Verbose(0) << "Cell size" << i << ": ";
    288             cin >> mol->cell_size[i];
    289           }
    290           break;
    291        
    292         case 'k': // ECut
    293           cout << Verbose(0) << "Old: " << config::ECut << "\t new: ";
    294           cin >> config::ECut;
    295           break;
    296         case 'l': // MaxLevel
    297           cout << Verbose(0) << "Old: " << config::MaxLevel << "\t new: ";
    298           cin >> config::MaxLevel;
    299           break;
    300         case 'm': // RiemannTensor
    301           cout << Verbose(0) << "Old: " << config::RiemannTensor << "\t new: ";
    302           cin >> config::RiemannTensor;
    303           break;
    304         case 'n': // LevRFactor
    305           cout << Verbose(0) << "Old: " << config::LevRFactor << "\t new: ";
    306           cin >> config::LevRFactor;
    307           break;
    308         case 'o': // RiemannLevel
    309           cout << Verbose(0) << "Old: " << config::RiemannLevel << "\t new: ";
    310           cin >> config::RiemannLevel;
    311           break;
    312         case 'p': // Lev0Factor
    313           cout << Verbose(0) << "Old: " << config::Lev0Factor << "\t new: ";
    314           cin >> config::Lev0Factor;
    315           break;
    316         case 'r': // RTActualUse
    317           cout << Verbose(0) << "Old: " << config::RTActualUse << "\t new: ";
    318           cin >> config::RTActualUse;
    319           break;
    320         case 's': // PsiType
    321           cout << Verbose(0) << "Old: " << config::PsiType << "\t new: ";
    322           cin >> config::PsiType;
    323           break;
    324         case 't': // MaxPsiDouble
    325           cout << Verbose(0) << "Old: " << config::MaxPsiDouble << "\t new: ";
    326           cin >> config::MaxPsiDouble;
    327           break;
    328         case 'u': // PsiMaxNoUp
    329           cout << Verbose(0) << "Old: " << config::PsiMaxNoUp << "\t new: ";
    330           cin >> config::PsiMaxNoUp;
    331           break;
    332         case 'v': // PsiMaxNoDown
    333           cout << Verbose(0) << "Old: " << config::PsiMaxNoDown << "\t new: ";
    334           cin >> config::PsiMaxNoDown;
    335           break;
    336         case 'w': // AddPsis
    337           cout << Verbose(0) << "Old: " << config::AddPsis << "\t new: ";
    338           cin >> config::AddPsis;
    339           break;
    340 
    341         case 'x': // RCut
    342           cout << Verbose(0) << "Old: " << config::RCut << "\t new: ";
    343           cin >> config::RCut;
    344           break;
    345         case 'y': // StructOpt
    346           cout << Verbose(0) << "Old: " << config::StructOpt << "\t new: ";
    347           cin >> config::StructOpt;
    348           break;
    349         case 'z': // IsAngstroem
    350           cout << Verbose(0) << "Old: " << config::IsAngstroem << "\t new: ";
    351           cin >> config::IsAngstroem;
    352           break;
    353         case 'i': // RelativeCoord
    354           cout << Verbose(0) << "Old: " << config::RelativeCoord << "\t new: ";
    355           cin >> config::RelativeCoord;
    356           break;
    357     };
    358   } while (choice != 'q');
     104        char choice;
     105       
     106        do {
     107                cout << Verbose(0) << "===========EDIT CONFIGURATION============================" << endl;
     108                cout << Verbose(0) << " A - mainname (prefix for all runtime files)" << endl;
     109                cout << Verbose(0) << " B - Default path (for runtime files)" << endl;
     110                cout << Verbose(0) << " C - Path of pseudopotential files" << endl;
     111                cout << Verbose(0) << " D - Number of coefficient sharing processes" << endl;
     112                cout << Verbose(0) << " E - Number of wave function sharing processes" << endl;
     113                cout << Verbose(0) << " F - 0: Don't output density for OpenDX, 1: do" << endl;
     114                cout << Verbose(0) << " G - 0: Don't output physical data, 1: do" << endl;
     115                cout << Verbose(0) << " H - 0: Don't output densities of each unperturbed orbital for OpenDX, 1: do" << endl;
     116                cout << Verbose(0) << " I - 0: Don't output current density for OpenDX, 1: do" << endl;
     117                cout << Verbose(0) << " J - 0: Don't do the full current calculation, 1: do" << endl;
     118                cout << Verbose(0) << " K - 0: Don't do perturbation calculation to obtain susceptibility and shielding, 1: do" << endl;
     119                cout << Verbose(0) << " L - 0: Wannier centres as calculated, 1: common centre for all, 2: unite centres according to spread, 3: cell centre, 4: shifted to nearest grid point" << endl;
     120                cout << Verbose(0) << " M - Absolute begin of unphysical sawtooth transfer for position operator within cell" << endl;
     121                cout << Verbose(0) << " N - (0,1,2) x,y,z-plane to do two-dimensional current vector cut" << endl;
     122                cout << Verbose(0) << " O - Absolute position along vector cut axis for cut plane" << endl;
     123                cout << Verbose(0) << " P - Additional Gram-Schmidt-Orthonormalization to stabilize numerics" << endl;
     124                cout << Verbose(0) << " Q - Initial integer value of random number generator" << endl;
     125                cout << Verbose(0) << " R - for perturbation 0, for structure optimization defines upper limit of iterations" << endl;
     126                cout << Verbose(0) << " T - Output visual after ...th step" << endl;
     127                cout << Verbose(0) << " U - Output source densities of wave functions after ...th step" << endl;
     128                cout << Verbose(0) << " X - minimization iterations per wave function, if unsure leave at default value 0" << endl;
     129                cout << Verbose(0) << " Y - tolerance value for total spread in iterative Jacobi diagonalization" << endl;
     130                cout << Verbose(0) << " Z - Maximum number of minimization iterations" << endl;
     131                cout << Verbose(0) << " a - Relative change in total energy to stop min. iteration" << endl;
     132                cout << Verbose(0) << " b - Relative change in kinetic energy to stop min. iteration" << endl;
     133                cout << Verbose(0) << " c - Check stop conditions every ..th step during min. iteration" << endl;
     134                cout << Verbose(0) << " e - Maximum number of minimization iterations during initial level" << endl;
     135                cout << Verbose(0) << " f - Relative change in total energy to stop min. iteration during initial level" << endl;
     136                cout << Verbose(0) << " g - Relative change in kinetic energy to stop min. iteration during initial level" << endl;
     137                cout << Verbose(0) << " h - Check stop conditions every ..th step during min. iteration during initial level" << endl;
     138                cout << Verbose(0) << " j - six lower diagonal entries of matrix, defining the unit cell" << endl;
     139                cout << Verbose(0) << " k - Energy cutoff of plane wave basis in Hartree" << endl;
     140                cout << Verbose(0) << " l - Maximum number of levels in multi-level-ansatz" << endl;
     141                cout << Verbose(0) << " m - Factor by which grid nodes increase between standard and upper level" << endl;
     142                cout << Verbose(0) << " n - 0: Don't use RiemannTensor, 1: Do" << endl;
     143                cout << Verbose(0) << " o - Factor by which grid nodes increase between Riemann and standard(?) level" << endl;
     144                cout << Verbose(0) << " p - Number of Riemann levels" << endl;
     145                cout << Verbose(0) << " r - 0: Don't Use RiemannTensor, 1: Do" << endl;
     146                cout << Verbose(0) << " s - 0: Doubly occupied orbitals, 1: Up-/Down-Orbitals" << endl;
     147                cout << Verbose(0) << " t - Number of orbitals (depends pn SpinType)" << endl;
     148                cout << Verbose(0) << " u - Number of SpinUp orbitals (depends on SpinType)" << endl;
     149                cout << Verbose(0) << " v - Number of SpinDown orbitals (depends on SpinType)" << endl;
     150                cout << Verbose(0) << " w - Number of additional, unoccupied orbitals" << endl;
     151                cout << Verbose(0) << " x - radial cutoff for ewald summation in Bohrradii" << endl;
     152                cout << Verbose(0) << " y - 0: Don't do structure optimization beforehand, 1: Do" << endl;
     153                cout << Verbose(0) << " z - 0: Units are in Bohr radii, 1: units are in Aengstrom" << endl;
     154                cout << Verbose(0) << " i - 0: Coordinates given in file are absolute, 1: ... are relative to unit cell" << endl;
     155                cout << Verbose(0) << "=========================================================" << endl;
     156                cout << Verbose(0) << "INPUT: ";
     157                cin >> choice;
     158               
     159                switch (choice) {
     160                                case 'A': // mainname
     161                                        cout << Verbose(0) << "Old: " << config::mainname << "\t new: ";
     162                                        cin >> config::mainname;
     163                                        break;
     164                                case 'B': // defaultpath
     165                                        cout << Verbose(0) << "Old: " << config::defaultpath << "\t new: ";
     166                                        cin >> config::defaultpath;
     167                                        break;
     168                                case 'C': // pseudopotpath
     169                                        cout << Verbose(0) << "Old: " << config::pseudopotpath << "\t new: ";
     170                                        cin >> config::pseudopotpath;
     171                                        break;
     172
     173                                case 'D': // ProcPEGamma
     174                                        cout << Verbose(0) << "Old: " << config::ProcPEGamma << "\t new: ";
     175                                        cin >> config::ProcPEGamma;
     176                                        break;
     177                                case 'E': // ProcPEPsi
     178                                        cout << Verbose(0) << "Old: " << config::ProcPEPsi << "\t new: ";
     179                                        cin >> config::ProcPEPsi;
     180                                        break;
     181                                case 'F': // DoOutVis
     182                                        cout << Verbose(0) << "Old: " << config::DoOutVis << "\t new: ";
     183                                        cin >> config::DoOutVis;
     184                                        break;
     185                                case 'G': // DoOutMes
     186                                        cout << Verbose(0) << "Old: " << config::DoOutMes << "\t new: ";
     187                                        cin >> config::DoOutMes;
     188                                        break;
     189                                case 'H': // DoOutOrbitals
     190                                        cout << Verbose(0) << "Old: " << config::DoOutOrbitals << "\t new: ";
     191                                        cin >> config::DoOutOrbitals;
     192                                        break;
     193                                case 'I': // DoOutCurrent
     194                                        cout << Verbose(0) << "Old: " << config::DoOutCurrent << "\t new: ";
     195                                        cin >> config::DoOutCurrent;
     196                                        break;
     197                                case 'J': // DoFullCurrent
     198                                        cout << Verbose(0) << "Old: " << config::DoFullCurrent << "\t new: ";
     199                                        cin >> config::DoFullCurrent;
     200                                        break;
     201                                case 'K': // DoPerturbation
     202                                        cout << Verbose(0) << "Old: " << config::DoPerturbation << "\t new: ";
     203                                        cin >> config::DoPerturbation;
     204                                        break;
     205                                case 'L': // CommonWannier
     206                                        cout << Verbose(0) << "Old: " << config::CommonWannier << "\t new: ";
     207                                        cin >> config::CommonWannier;
     208                                        break;
     209                                case 'M': // SawtoothStart
     210                                        cout << Verbose(0) << "Old: " << config::SawtoothStart << "\t new: ";
     211                                        cin >> config::SawtoothStart;
     212                                        break;
     213                                case 'N': // VectorPlane
     214                                        cout << Verbose(0) << "Old: " << config::VectorPlane << "\t new: ";
     215                                        cin >> config::VectorPlane;
     216                                        break;
     217                                case 'O': // VectorCut
     218                                        cout << Verbose(0) << "Old: " << config::VectorCut << "\t new: ";
     219                                        cin >> config::VectorCut;
     220                                        break;
     221                                case 'P': // UseAddGramSch
     222                                        cout << Verbose(0) << "Old: " << config::UseAddGramSch << "\t new: ";
     223                                        cin >> config::UseAddGramSch;
     224                                        break;
     225                                case 'Q': // Seed
     226                                        cout << Verbose(0) << "Old: " << config::Seed << "\t new: ";
     227                                        cin >> config::Seed;
     228                                        break;
     229
     230                                case 'R': // MaxOuterStep
     231                                        cout << Verbose(0) << "Old: " << config::MaxOuterStep << "\t new: ";
     232                                        cin >> config::MaxOuterStep;
     233                                        break;
     234                                case 'T': // OutVisStep
     235                                        cout << Verbose(0) << "Old: " << config::OutVisStep << "\t new: ";
     236                                        cin >> config::OutVisStep;
     237                                        break;
     238                                case 'U': // OutSrcStep
     239                                        cout << Verbose(0) << "Old: " << config::OutSrcStep << "\t new: ";
     240                                        cin >> config::OutSrcStep;
     241                                        break;
     242                                case 'X': // MaxPsiStep
     243                                        cout << Verbose(0) << "Old: " << config::MaxPsiStep << "\t new: ";
     244                                        cin >> config::MaxPsiStep;
     245                                        break;
     246                                case 'Y': // EpsWannier
     247                                        cout << Verbose(0) << "Old: " << config::EpsWannier << "\t new: ";
     248                                        cin >> config::EpsWannier;
     249                                        break;
     250
     251                                case 'Z': // MaxMinStep
     252                                        cout << Verbose(0) << "Old: " << config::MaxMinStep << "\t new: ";
     253                                        cin >> config::MaxMinStep;
     254                                        break;
     255                                case 'a': // RelEpsTotalEnergy
     256                                        cout << Verbose(0) << "Old: " << config::RelEpsTotalEnergy << "\t new: ";
     257                                        cin >> config::RelEpsTotalEnergy;
     258                                        break;
     259                                case 'b': // RelEpsKineticEnergy
     260                                        cout << Verbose(0) << "Old: " << config::RelEpsKineticEnergy << "\t new: ";
     261                                        cin >> config::RelEpsKineticEnergy;
     262                                        break;
     263                                case 'c': // MaxMinStopStep
     264                                        cout << Verbose(0) << "Old: " << config::MaxMinStopStep << "\t new: ";
     265                                        cin >> config::MaxMinStopStep;
     266                                        break;
     267                                case 'e': // MaxInitMinStep
     268                                        cout << Verbose(0) << "Old: " << config::MaxInitMinStep << "\t new: ";
     269                                        cin >> config::MaxInitMinStep;
     270                                        break;
     271                                case 'f': // InitRelEpsTotalEnergy
     272                                        cout << Verbose(0) << "Old: " << config::InitRelEpsTotalEnergy << "\t new: ";
     273                                        cin >> config::InitRelEpsTotalEnergy;
     274                                        break;
     275                                case 'g': // InitRelEpsKineticEnergy
     276                                        cout << Verbose(0) << "Old: " << config::InitRelEpsKineticEnergy << "\t new: ";
     277                                        cin >> config::InitRelEpsKineticEnergy;
     278                                        break;
     279                                case 'h': // InitMaxMinStopStep
     280                                        cout << Verbose(0) << "Old: " << config::InitMaxMinStopStep << "\t new: ";
     281                                        cin >> config::InitMaxMinStopStep;
     282                                        break;
     283                               
     284                                case 'j': // BoxLength
     285                                        cout << Verbose(0) << "enter lower triadiagonalo form of basis matrix" << endl << endl;
     286                                        for (int i=0;i<6;i++) {
     287                                                cout << Verbose(0) << "Cell size" << i << ": ";
     288                                                cin >> mol->cell_size[i];
     289                                        }
     290                                        break;
     291                               
     292                                case 'k': // ECut
     293                                        cout << Verbose(0) << "Old: " << config::ECut << "\t new: ";
     294                                        cin >> config::ECut;
     295                                        break;
     296                                case 'l': // MaxLevel
     297                                        cout << Verbose(0) << "Old: " << config::MaxLevel << "\t new: ";
     298                                        cin >> config::MaxLevel;
     299                                        break;
     300                                case 'm': // RiemannTensor
     301                                        cout << Verbose(0) << "Old: " << config::RiemannTensor << "\t new: ";
     302                                        cin >> config::RiemannTensor;
     303                                        break;
     304                                case 'n': // LevRFactor
     305                                        cout << Verbose(0) << "Old: " << config::LevRFactor << "\t new: ";
     306                                        cin >> config::LevRFactor;
     307                                        break;
     308                                case 'o': // RiemannLevel
     309                                        cout << Verbose(0) << "Old: " << config::RiemannLevel << "\t new: ";
     310                                        cin >> config::RiemannLevel;
     311                                        break;
     312                                case 'p': // Lev0Factor
     313                                        cout << Verbose(0) << "Old: " << config::Lev0Factor << "\t new: ";
     314                                        cin >> config::Lev0Factor;
     315                                        break;
     316                                case 'r': // RTActualUse
     317                                        cout << Verbose(0) << "Old: " << config::RTActualUse << "\t new: ";
     318                                        cin >> config::RTActualUse;
     319                                        break;
     320                                case 's': // PsiType
     321                                        cout << Verbose(0) << "Old: " << config::PsiType << "\t new: ";
     322                                        cin >> config::PsiType;
     323                                        break;
     324                                case 't': // MaxPsiDouble
     325                                        cout << Verbose(0) << "Old: " << config::MaxPsiDouble << "\t new: ";
     326                                        cin >> config::MaxPsiDouble;
     327                                        break;
     328                                case 'u': // PsiMaxNoUp
     329                                        cout << Verbose(0) << "Old: " << config::PsiMaxNoUp << "\t new: ";
     330                                        cin >> config::PsiMaxNoUp;
     331                                        break;
     332                                case 'v': // PsiMaxNoDown
     333                                        cout << Verbose(0) << "Old: " << config::PsiMaxNoDown << "\t new: ";
     334                                        cin >> config::PsiMaxNoDown;
     335                                        break;
     336                                case 'w': // AddPsis
     337                                        cout << Verbose(0) << "Old: " << config::AddPsis << "\t new: ";
     338                                        cin >> config::AddPsis;
     339                                        break;
     340
     341                                case 'x': // RCut
     342                                        cout << Verbose(0) << "Old: " << config::RCut << "\t new: ";
     343                                        cin >> config::RCut;
     344                                        break;
     345                                case 'y': // StructOpt
     346                                        cout << Verbose(0) << "Old: " << config::StructOpt << "\t new: ";
     347                                        cin >> config::StructOpt;
     348                                        break;
     349                                case 'z': // IsAngstroem
     350                                        cout << Verbose(0) << "Old: " << config::IsAngstroem << "\t new: ";
     351                                        cin >> config::IsAngstroem;
     352                                        break;
     353                                case 'i': // RelativeCoord
     354                                        cout << Verbose(0) << "Old: " << config::RelativeCoord << "\t new: ";
     355                                        cin >> config::RelativeCoord;
     356                                        break;
     357                };
     358        } while (choice != 'q');
    359359};
    360360
     
    367367int config::TestSyntax(char *filename, periodentafel *periode, molecule *mol)
    368368{
    369   int test;
    370   ifstream file(filename);
    371  
    372   // search file for keyword: ProcPEGamma (new syntax)
    373   if (ParseForParameter(1,&file,"ProcPEGamma", 0, 1, 1, int_type, &test, 1, optional)) {
    374     file.close();
    375     return 1;
    376   }
    377   // search file for keyword: ProcsGammaPsi (old syntax)
    378   if (ParseForParameter(1,&file,"ProcsGammaPsi", 0, 1, 1, int_type, &test, 1, optional)) {
    379     file.close();
    380     return 0;
    381   }
    382   file.close();
    383   return -1;
     369        int test;
     370        ifstream file(filename);
     371       
     372        // search file for keyword: ProcPEGamma (new syntax)
     373        if (ParseForParameter(1,&file,"ProcPEGamma", 0, 1, 1, int_type, &test, 1, optional)) {
     374                file.close();
     375                return 1;
     376        }
     377        // search file for keyword: ProcsGammaPsi (old syntax)
     378        if (ParseForParameter(1,&file,"ProcsGammaPsi", 0, 1, 1, int_type, &test, 1, optional)) {
     379                file.close();
     380                return 0;
     381        }
     382        file.close();
     383        return -1;
    384384}
    385385
     
    389389bool config::GetIsAngstroem() const
    390390{
    391   return (IsAngstroem == 1);
     391        return (IsAngstroem == 1);
    392392};
    393393
     
    397397char * config::GetDefaultPath() const
    398398{
    399   return defaultpath;
     399        return defaultpath;
    400400};
    401401
     
    406406void config::SetDefaultPath(const char *path)
    407407{
    408   strcpy(defaultpath, path);
     408        strcpy(defaultpath, path);
    409409};
    410410
     
    414414void config::RetrieveConfigPathAndName(string filename)
    415415{
    416   char *ptr = NULL;
    417   char *buffer = new char[MAXSTRINGSIZE];
    418   strncpy(buffer, filename.c_str(), MAXSTRINGSIZE);
    419   int last = -1;
    420   for(last=MAXSTRINGSIZE;last--;) {
    421     if (buffer[last] == '/')
    422       break;
    423   }
    424   if (last == -1) { // no path in front, set to local directory.
    425     strcpy(configpath, "./");
    426     ptr = buffer;
    427   } else {
    428     strncpy(configpath, buffer, last+1);
    429     ptr = &buffer[last+1];
    430     if (last < 254)
    431       configpath[last+1]='\0';
    432   }
    433   strcpy(configname, ptr);
    434   cout << "Found configpath: " << configpath << ", dir slash was found at " << last << ", config name is " << configname << "." << endl;
    435   delete[](buffer);
     416        char *ptr = NULL;
     417        char *buffer = new char[MAXSTRINGSIZE];
     418        strncpy(buffer, filename.c_str(), MAXSTRINGSIZE);
     419        int last = -1;
     420        for(last=MAXSTRINGSIZE;last--;) {
     421                if (buffer[last] == '/')
     422                        break;
     423        }
     424        if (last == -1) { // no path in front, set to local directory.
     425                strcpy(configpath, "./");
     426                ptr = buffer;
     427        } else {
     428                strncpy(configpath, buffer, last+1);
     429                ptr = &buffer[last+1];
     430                if (last < 254)
     431                        configpath[last+1]='\0';
     432        }
     433        strcpy(configname, ptr);
     434        cout << "Found configpath: " << configpath << ", dir slash was found at " << last << ", config name is " << configname << "." << endl;
     435        delete[](buffer);
    436436};
    437437
     
    444444void config::Load(char *filename, periodentafel *periode, molecule *mol)
    445445{
    446   ifstream *file = new ifstream(filename);
    447   if (file == NULL) {
    448     cerr << "ERROR: config file " << filename << " missing!" << endl;
    449     return;
    450   }
    451   RetrieveConfigPathAndName(filename);
    452   // ParseParameters
    453  
    454   /* Oeffne Hauptparameterdatei */
    455   int di;
    456   double BoxLength[9];
    457   string zeile;
    458   string dummy;
    459   element *elementhash[MAX_ELEMENTS];
    460   char name[MAX_ELEMENTS];
    461   char keyword[MAX_ELEMENTS];
    462   int Z, No[MAX_ELEMENTS];
    463   int verbose = 0;
    464   double value[3];
    465  
    466   /* Namen einlesen */
    467 
    468   ParseForParameter(verbose,file, "mainname", 0, 1, 1, string_type, (config::mainname), 1, critical);
    469   ParseForParameter(verbose,file, "defaultpath", 0, 1, 1, string_type, (config::defaultpath), 1, critical);
    470   ParseForParameter(verbose,file, "pseudopotpath", 0, 1, 1, string_type, (config::pseudopotpath), 1, critical);
    471   ParseForParameter(verbose,file,"ProcPEGamma", 0, 1, 1, int_type, &(config::ProcPEGamma), 1, critical);
    472   ParseForParameter(verbose,file,"ProcPEPsi", 0, 1, 1, int_type, &(config::ProcPEPsi), 1, critical);
    473 
    474   if (!ParseForParameter(verbose,file,"Seed", 0, 1, 1, int_type, &(config::Seed), 1, optional))
    475     config::Seed = 1;
    476 
    477   if(!ParseForParameter(verbose,file,"DoOutOrbitals", 0, 1, 1, int_type, &(config::DoOutOrbitals), 1, optional)) {
    478     config::DoOutOrbitals = 0;
    479   } else {
    480     if (config::DoOutOrbitals < 0) config::DoOutOrbitals = 0;
    481     if (config::DoOutOrbitals > 1) config::DoOutOrbitals = 1;
    482   }
    483   ParseForParameter(verbose,file,"DoOutVis", 0, 1, 1, int_type, &(config::DoOutVis), 1, critical);
    484   if (config::DoOutVis < 0) config::DoOutVis = 0;
    485   if (config::DoOutVis > 1) config::DoOutVis = 1;
    486   if (!ParseForParameter(verbose,file,"VectorPlane", 0, 1, 1, int_type, &(config::VectorPlane), 1, optional))
    487     config::VectorPlane = -1;
    488   if (!ParseForParameter(verbose,file,"VectorCut", 0, 1, 1, double_type, &(config::VectorCut), 1, optional))
    489     config::VectorCut = 0.;
    490   ParseForParameter(verbose,file,"DoOutMes", 0, 1, 1, int_type, &(config::DoOutMes), 1, critical);
    491   if (config::DoOutMes < 0) config::DoOutMes = 0;
    492   if (config::DoOutMes > 1) config::DoOutMes = 1;
    493   if (!ParseForParameter(verbose,file,"DoOutCurr", 0, 1, 1, int_type, &(config::DoOutCurrent), 1, optional))
    494     config::DoOutCurrent = 0;
    495   if (config::DoOutCurrent < 0) config::DoOutCurrent = 0;
    496   if (config::DoOutCurrent > 1) config::DoOutCurrent = 1;
    497   ParseForParameter(verbose,file,"AddGramSch", 0, 1, 1, int_type, &(config::UseAddGramSch), 1, critical);
    498   if (config::UseAddGramSch < 0) config::UseAddGramSch = 0;
    499   if (config::UseAddGramSch > 2) config::UseAddGramSch = 2;
    500   if(!ParseForParameter(verbose,file,"DoWannier", 0, 1, 1, int_type, &(config::DoWannier), 1, optional)) {
    501     config::DoWannier = 0;
    502   } else {
    503     if (config::DoWannier < 0) config::DoWannier = 0;
    504     if (config::DoWannier > 1) config::DoWannier = 1;
    505   }
    506   if(!ParseForParameter(verbose,file,"CommonWannier", 0, 1, 1, int_type, &(config::CommonWannier), 1, optional)) {
    507     config::CommonWannier = 0;
    508   } else {
    509     if (config::CommonWannier < 0) config::CommonWannier = 0;
    510     if (config::CommonWannier > 4) config::CommonWannier = 4;
    511   }
    512   if(!ParseForParameter(verbose,file,"SawtoothStart", 0, 1, 1, double_type, &(config::SawtoothStart), 1, optional)) {
    513     config::SawtoothStart = 0.01;
    514   } else {
    515     if (config::SawtoothStart < 0.) config::SawtoothStart = 0.;
    516     if (config::SawtoothStart > 1.) config::SawtoothStart = 1.;
    517   }
    518  
    519   ParseForParameter(verbose,file,"MaxOuterStep", 0, 1, 1, int_type, &(config::MaxOuterStep), 1, critical);
    520   if (!ParseForParameter(verbose,file,"Deltat", 0, 1, 1, double_type, &(config::Deltat), 1, optional))
    521     config::Deltat = 1;
    522   ParseForParameter(verbose,file,"OutVisStep", 0, 1, 1, int_type, &(config::OutVisStep), 1, optional);
    523   ParseForParameter(verbose,file,"OutSrcStep", 0, 1, 1, int_type, &(config::OutSrcStep), 1, optional);
    524   ParseForParameter(verbose,file,"TargetTemp", 0, 1, 1, double_type, &(config::TargetTemp), 1, optional);
    525   //ParseForParameter(verbose,file,"Thermostat", 0, 1, 1, int_type, &(config::ScaleTempStep), 1, optional);
    526   if (!ParseForParameter(verbose,file,"EpsWannier", 0, 1, 1, double_type, &(config::EpsWannier), 1, optional))
    527     config::EpsWannier = 1e-8;
    528  
    529   // stop conditions
    530   //if (config::MaxOuterStep <= 0) config::MaxOuterStep = 1;
    531   ParseForParameter(verbose,file,"MaxPsiStep", 0, 1, 1, int_type, &(config::MaxPsiStep), 1, critical);
    532   if (config::MaxPsiStep <= 0) config::MaxPsiStep = 3;
    533  
    534   ParseForParameter(verbose,file,"MaxMinStep", 0, 1, 1, int_type, &(config::MaxMinStep), 1, critical);
    535   ParseForParameter(verbose,file,"RelEpsTotalE", 0, 1, 1, double_type, &(config::RelEpsTotalEnergy), 1, critical);
    536   ParseForParameter(verbose,file,"RelEpsKineticE", 0, 1, 1, double_type, &(config::RelEpsKineticEnergy), 1, critical);
    537   ParseForParameter(verbose,file,"MaxMinStopStep", 0, 1, 1, int_type, &(config::MaxMinStopStep), 1, critical);
    538   ParseForParameter(verbose,file,"MaxMinGapStopStep", 0, 1, 1, int_type, &(config::MaxMinGapStopStep), 1, critical);
    539   if (config::MaxMinStep <= 0) config::MaxMinStep = config::MaxPsiStep;
    540   if (config::MaxMinStopStep < 1) config::MaxMinStopStep = 1;
    541   if (config::MaxMinGapStopStep < 1) config::MaxMinGapStopStep = 1;
    542  
    543   ParseForParameter(verbose,file,"MaxInitMinStep", 0, 1, 1, int_type, &(config::MaxInitMinStep), 1, critical);
    544   ParseForParameter(verbose,file,"InitRelEpsTotalE", 0, 1, 1, double_type, &(config::InitRelEpsTotalEnergy), 1, critical);
    545   ParseForParameter(verbose,file,"InitRelEpsKineticE", 0, 1, 1, double_type, &(config::InitRelEpsKineticEnergy), 1, critical);
    546   ParseForParameter(verbose,file,"InitMaxMinStopStep", 0, 1, 1, int_type, &(config::InitMaxMinStopStep), 1, critical);
    547   ParseForParameter(verbose,file,"InitMaxMinGapStopStep", 0, 1, 1, int_type, &(config::InitMaxMinGapStopStep), 1, critical);
    548   if (config::MaxInitMinStep <= 0) config::MaxInitMinStep = config::MaxPsiStep;
    549   if (config::InitMaxMinStopStep < 1) config::InitMaxMinStopStep = 1;
    550   if (config::InitMaxMinGapStopStep < 1) config::InitMaxMinGapStopStep = 1;
    551  
    552   // Unit cell and magnetic field
    553   ParseForParameter(verbose,file, "BoxLength", 0, 3, 3, lower_trigrid, BoxLength, 1, critical); /* Lattice->RealBasis */
    554   mol->cell_size[0] = BoxLength[0];
    555   mol->cell_size[1] = BoxLength[3];
    556   mol->cell_size[2] = BoxLength[4];
    557   mol->cell_size[3] = BoxLength[6];
    558   mol->cell_size[4] = BoxLength[7];
    559   mol->cell_size[5] = BoxLength[8];
    560   if (1) fprintf(stderr,"\n");
    561 
    562   ParseForParameter(verbose,file,"DoPerturbation", 0, 1, 1, int_type, &(config::DoPerturbation), 1, optional);
    563   ParseForParameter(verbose,file,"DoOutNICS", 0, 1, 1, int_type, &(config::DoOutNICS), 1, optional);
    564   if (!ParseForParameter(verbose,file,"DoFullCurrent", 0, 1, 1, int_type, &(config::DoFullCurrent), 1, optional))
    565     config::DoFullCurrent = 0;
    566   if (config::DoFullCurrent < 0) config::DoFullCurrent = 0;
    567   if (config::DoFullCurrent > 2) config::DoFullCurrent = 2;
    568   if (config::DoOutNICS < 0) config::DoOutNICS = 0;
    569   if (config::DoOutNICS > 2) config::DoOutNICS = 2;
    570   if (config::DoPerturbation == 0) {
    571     config::DoFullCurrent = 0;
    572     config::DoOutNICS = 0;
    573   }
    574 
    575   ParseForParameter(verbose,file,"ECut", 0, 1, 1, double_type, &(config::ECut), 1, critical);
    576   ParseForParameter(verbose,file,"MaxLevel", 0, 1, 1, int_type, &(config::MaxLevel), 1, critical);
    577   ParseForParameter(verbose,file,"Level0Factor", 0, 1, 1, int_type, &(config::Lev0Factor), 1, critical);
    578   if (config::Lev0Factor < 2) {
    579     config::Lev0Factor = 2;
    580   }
    581   ParseForParameter(verbose,file,"RiemannTensor", 0, 1, 1, int_type, &di, 1, critical);
    582   if (di >= 0 && di < 2) {
    583     config::RiemannTensor = di;
    584   } else {
    585     fprintf(stderr, "0 <= RiemanTensor < 2: 0 UseNotRT, 1 UseRT");
    586     exit(1);
    587   }
    588   switch (config::RiemannTensor) {
    589     case 0: //UseNoRT
    590       if (config::MaxLevel < 2) {
    591         config::MaxLevel = 2;
    592       }
    593       config::LevRFactor = 2;
    594       config::RTActualUse = 0;
    595       break;
    596     case 1: // UseRT
    597       if (config::MaxLevel < 3) {
    598         config::MaxLevel = 3;
    599       }
    600       ParseForParameter(verbose,file,"RiemannLevel", 0, 1, 1, int_type, &(config::RiemannLevel), 1, critical);
    601       if (config::RiemannLevel < 2) {
    602         config::RiemannLevel = 2;
    603       }
    604       if (config::RiemannLevel > config::MaxLevel-1) {
    605         config::RiemannLevel = config::MaxLevel-1;
    606       }
    607       ParseForParameter(verbose,file,"LevRFactor", 0, 1, 1, int_type, &(config::LevRFactor), 1, critical);
    608       if (config::LevRFactor < 2) {
    609         config::LevRFactor = 2;
    610       }
    611       config::Lev0Factor = 2;
    612       config::RTActualUse = 2;
    613       break;
    614   }
    615   ParseForParameter(verbose,file,"PsiType", 0, 1, 1, int_type, &di, 1, critical);
    616   if (di >= 0 && di < 2) {
    617     config::PsiType = di;
    618   } else {
    619     fprintf(stderr, "0 <= PsiType < 2: 0 UseSpinDouble, 1 UseSpinUpDown");
    620     exit(1);
    621   }
    622   switch (config::PsiType) {
    623   case 0: // SpinDouble
    624     ParseForParameter(verbose,file,"MaxPsiDouble", 0, 1, 1, int_type, &(config::MaxPsiDouble), 1, critical);
    625     ParseForParameter(verbose,file,"AddPsis", 0, 1, 1, int_type, &(config::AddPsis), 1, optional);
    626     break;
    627   case 1: // SpinUpDown
    628     if (config::ProcPEGamma % 2) config::ProcPEGamma*=2;
    629     ParseForParameter(verbose,file,"PsiMaxNoUp", 0, 1, 1, int_type, &(config::PsiMaxNoUp), 1, critical);
    630     ParseForParameter(verbose,file,"PsiMaxNoDown", 0, 1, 1, int_type, &(config::PsiMaxNoDown), 1, critical);
    631     ParseForParameter(verbose,file,"AddPsis", 0, 1, 1, int_type, &(config::AddPsis), 1, optional);
    632     break;
    633   }
    634  
    635   // IonsInitRead
    636  
    637   ParseForParameter(verbose,file,"RCut", 0, 1, 1, double_type, &(config::RCut), 1, critical);
    638   ParseForParameter(verbose,file,"IsAngstroem", 0, 1, 1, int_type, &(config::IsAngstroem), 1, critical);
    639   ParseForParameter(verbose,file,"MaxTypes", 0, 1, 1, int_type, &(config::MaxTypes), 1, critical);
    640   if (!ParseForParameter(verbose,file,"RelativeCoord", 0, 1, 1, int_type, &(config::RelativeCoord) , 1, optional))
    641     config::RelativeCoord = 0;
    642   if (!ParseForParameter(verbose,file,"StructOpt", 0, 1, 1, int_type, &(config::StructOpt), 1, optional))
    643     config::StructOpt = 0;
    644   if (MaxTypes == 0) {
    645     cerr << "There are no atoms according to MaxTypes in this config file." << endl;
    646   } else {
    647     // prescan number of ions per type
    648     cout << Verbose(0) << "Prescanning ions per type: " << endl;
    649     for (int i=0; i < config::MaxTypes; i++) {
    650       sprintf(name,"Ion_Type%i",i+1);
    651       ParseForParameter(verbose,file, (const char*)name, 0, 1, 1, int_type, &No[i], 1, critical);
    652       ParseForParameter(verbose,file, name, 0, 2, 1, int_type, &Z, 1, critical);
    653       elementhash[i] = periode->FindElement(Z);
    654       cout << Verbose(1) << i << ". Z = " << elementhash[i]->Z << " with " << No[i] << " ions." << endl;
    655     }
    656     int repetition = 0; // which repeated keyword shall be read
    657  
    658     map<int, atom *> AtomList[config::MaxTypes];
    659     if (!FastParsing) {
    660       // parse in trajectories
    661       bool status = true;
    662       atom *neues = NULL;
    663       while (status) {
    664         cout << "Currently parsing MD step " << repetition << "." << endl;
    665         for (int i=0; i < config::MaxTypes; i++) {
    666           sprintf(name,"Ion_Type%i",i+1);
    667           for(int j=0;j<No[i];j++) {
    668             sprintf(keyword,"%s_%i",name, j+1);
    669             if (repetition == 0) {
    670               neues = new atom();
    671               AtomList[i][j] = neues;
    672               neues->type = elementhash[i]; // find element type
    673               mol->AddAtom(neues);
    674             } else
    675               neues = AtomList[i][j];
    676             status = (status &&
    677                     ParseForParameter(verbose,file, keyword, 0, 1, 1, double_type, &neues->x.x[0], 1, (repetition == 0) ? critical : optional) &&
    678                     ParseForParameter(verbose,file, keyword, 0, 2, 1, double_type, &neues->x.x[1], 1, (repetition == 0) ? critical : optional) &&
    679                     ParseForParameter(verbose,file, keyword, 0, 3, 1, double_type, &neues->x.x[2], 1, (repetition == 0) ? critical : optional) &&
    680                     ParseForParameter(verbose,file, keyword, 0, 4, 1, int_type, &neues->FixedIon, 1, (repetition == 0) ? critical : optional));
    681             if (!status) break;
    682    
    683             // check size of vectors
    684             if (mol->Trajectories[neues].R.size() <= (unsigned int)(repetition)) {
    685               //cout << "Increasing size for trajectory array of " << keyword << " to " << (repetition+10) << "." << endl;
    686               mol->Trajectories[neues].R.resize(repetition+10);
    687               mol->Trajectories[neues].U.resize(repetition+10);
    688               mol->Trajectories[neues].F.resize(repetition+10);
    689             }
    690          
    691             // put into trajectories list
    692             for (int d=0;d<NDIM;d++)
    693               mol->Trajectories[neues].R.at(repetition).x[d] = neues->x.x[d];
    694            
    695             // parse velocities if present
    696             if(!ParseForParameter(verbose,file, keyword, 0, 5, 1, double_type, &neues->v.x[0], 1,optional))
    697               neues->v.x[0] = 0.;
    698             if(!ParseForParameter(verbose,file, keyword, 0, 6, 1, double_type, &neues->v.x[1], 1,optional))
    699               neues->v.x[1] = 0.;
    700             if(!ParseForParameter(verbose,file, keyword, 0, 7, 1, double_type, &neues->v.x[2], 1,optional))
    701               neues->v.x[2] = 0.;
    702             for (int d=0;d<NDIM;d++)
    703               mol->Trajectories[neues].U.at(repetition).x[d] = neues->v.x[d];
    704      
    705             // parse forces if present
    706             if(!ParseForParameter(verbose,file, keyword, 0, 8, 1, double_type, &value[0], 1,optional))
    707               value[0] = 0.;
    708             if(!ParseForParameter(verbose,file, keyword, 0, 9, 1, double_type, &value[1], 1,optional))
    709               value[1] = 0.;
    710             if(!ParseForParameter(verbose,file, keyword, 1, 10, 1, double_type, &value[2], 1,optional))
    711               value[2] = 0.;
    712             for (int d=0;d<NDIM;d++)
    713               mol->Trajectories[neues].F.at(repetition).x[d] = value[d];
    714  
    715   //            cout << "Parsed position of step " << (repetition) << ": (";
    716   //            for (int d=0;d<NDIM;d++)
    717   //              cout << mol->Trajectories[neues].R.at(repetition).x[d] << " ";          // next step
    718   //            cout << ")\t(";
    719   //            for (int d=0;d<NDIM;d++)
    720   //              cout << mol->Trajectories[neues].U.at(repetition).x[d] << " ";          // next step
    721   //            cout << ")\t(";
    722   //            for (int d=0;d<NDIM;d++)
    723   //              cout << mol->Trajectories[neues].F.at(repetition).x[d] << " ";          // next step
    724   //            cout << ")" << endl;
    725           }
    726         }
    727         repetition++;
    728       }
    729       repetition--;
    730       cout << "Found " << repetition << " trajectory steps." << endl;
    731       mol->MDSteps = repetition;
    732     } else {
    733       // find the maximum number of MD steps so that we may parse last one (Ion_Type1_1 must always be present, because is the first atom)
    734       repetition = 0;
    735       while ( ParseForParameter(verbose,file, "Ion_Type1_1", 0, 1, 1, double_type, &value[0], repetition, (repetition == 0) ? critical : optional) &&
    736               ParseForParameter(verbose,file, "Ion_Type1_1", 0, 2, 1, double_type, &value[1], repetition, (repetition == 0) ? critical : optional) &&
    737               ParseForParameter(verbose,file, "Ion_Type1_1", 0, 3, 1, double_type, &value[2], repetition, (repetition == 0) ? critical : optional))
    738         repetition++;
    739       cout << "I found " << repetition << " times the keyword Ion_Type1_1." << endl;
    740       // parse in molecule coordinates
    741       for (int i=0; i < config::MaxTypes; i++) {
    742         sprintf(name,"Ion_Type%i",i+1);
    743         for(int j=0;j<No[i];j++) {
    744           sprintf(keyword,"%s_%i",name, j+1);
    745           atom *neues = new atom();
    746           // then parse for each atom the coordinates as often as present
    747           ParseForParameter(verbose,file, keyword, 0, 1, 1, double_type, &neues->x.x[0], repetition,critical);
    748           ParseForParameter(verbose,file, keyword, 0, 2, 1, double_type, &neues->x.x[1], repetition,critical);
    749           ParseForParameter(verbose,file, keyword, 0, 3, 1, double_type, &neues->x.x[2], repetition,critical);
    750           ParseForParameter(verbose,file, keyword, 0, 4, 1, int_type, &neues->FixedIon, repetition,critical);
    751           if(!ParseForParameter(verbose,file, keyword, 0, 5, 1, double_type, &neues->v.x[0], repetition,optional))
    752             neues->v.x[0] = 0.;
    753           if(!ParseForParameter(verbose,file, keyword, 0, 6, 1, double_type, &neues->v.x[1], repetition,optional))
    754             neues->v.x[1] = 0.;
    755           if(!ParseForParameter(verbose,file, keyword, 0, 7, 1, double_type, &neues->v.x[2], repetition,optional))
    756             neues->v.x[2] = 0.;
    757           // here we don't care if forces are present (last in trajectories is always equal to current position)
    758           neues->type = elementhash[i]; // find element type
    759           mol->AddAtom(neues);
    760         }
    761       }
    762     }
    763   }
    764   file->close();
    765   delete(file);
     446        ifstream *file = new ifstream(filename);
     447        if (file == NULL) {
     448                cerr << "ERROR: config file " << filename << " missing!" << endl;
     449                return;
     450        }
     451        RetrieveConfigPathAndName(filename);
     452        // ParseParameters
     453       
     454        /* Oeffne Hauptparameterdatei */
     455        int di;
     456        double BoxLength[9];
     457        string zeile;
     458        string dummy;
     459        element *elementhash[MAX_ELEMENTS];
     460        char name[MAX_ELEMENTS];
     461        char keyword[MAX_ELEMENTS];
     462        int Z, No[MAX_ELEMENTS];
     463        int verbose = 0;
     464        double value[3];
     465       
     466        /* Namen einlesen */
     467
     468        ParseForParameter(verbose,file, "mainname", 0, 1, 1, string_type, (config::mainname), 1, critical);
     469        ParseForParameter(verbose,file, "defaultpath", 0, 1, 1, string_type, (config::defaultpath), 1, critical);
     470        ParseForParameter(verbose,file, "pseudopotpath", 0, 1, 1, string_type, (config::pseudopotpath), 1, critical);
     471        ParseForParameter(verbose,file,"ProcPEGamma", 0, 1, 1, int_type, &(config::ProcPEGamma), 1, critical);
     472        ParseForParameter(verbose,file,"ProcPEPsi", 0, 1, 1, int_type, &(config::ProcPEPsi), 1, critical);
     473
     474        if (!ParseForParameter(verbose,file,"Seed", 0, 1, 1, int_type, &(config::Seed), 1, optional))
     475                config::Seed = 1;
     476
     477        if(!ParseForParameter(verbose,file,"DoOutOrbitals", 0, 1, 1, int_type, &(config::DoOutOrbitals), 1, optional)) {
     478                config::DoOutOrbitals = 0;
     479        } else {
     480                if (config::DoOutOrbitals < 0) config::DoOutOrbitals = 0;
     481                if (config::DoOutOrbitals > 1) config::DoOutOrbitals = 1;
     482        }
     483        ParseForParameter(verbose,file,"DoOutVis", 0, 1, 1, int_type, &(config::DoOutVis), 1, critical);
     484        if (config::DoOutVis < 0) config::DoOutVis = 0;
     485        if (config::DoOutVis > 1) config::DoOutVis = 1;
     486        if (!ParseForParameter(verbose,file,"VectorPlane", 0, 1, 1, int_type, &(config::VectorPlane), 1, optional))
     487                config::VectorPlane = -1;
     488        if (!ParseForParameter(verbose,file,"VectorCut", 0, 1, 1, double_type, &(config::VectorCut), 1, optional))
     489                config::VectorCut = 0.;
     490        ParseForParameter(verbose,file,"DoOutMes", 0, 1, 1, int_type, &(config::DoOutMes), 1, critical);
     491        if (config::DoOutMes < 0) config::DoOutMes = 0;
     492        if (config::DoOutMes > 1) config::DoOutMes = 1;
     493        if (!ParseForParameter(verbose,file,"DoOutCurr", 0, 1, 1, int_type, &(config::DoOutCurrent), 1, optional))
     494                config::DoOutCurrent = 0;
     495        if (config::DoOutCurrent < 0) config::DoOutCurrent = 0;
     496        if (config::DoOutCurrent > 1) config::DoOutCurrent = 1;
     497        ParseForParameter(verbose,file,"AddGramSch", 0, 1, 1, int_type, &(config::UseAddGramSch), 1, critical);
     498        if (config::UseAddGramSch < 0) config::UseAddGramSch = 0;
     499        if (config::UseAddGramSch > 2) config::UseAddGramSch = 2;
     500        if(!ParseForParameter(verbose,file,"DoWannier", 0, 1, 1, int_type, &(config::DoWannier), 1, optional)) {
     501                config::DoWannier = 0;
     502        } else {
     503                if (config::DoWannier < 0) config::DoWannier = 0;
     504                if (config::DoWannier > 1) config::DoWannier = 1;
     505        }
     506        if(!ParseForParameter(verbose,file,"CommonWannier", 0, 1, 1, int_type, &(config::CommonWannier), 1, optional)) {
     507                config::CommonWannier = 0;
     508        } else {
     509                if (config::CommonWannier < 0) config::CommonWannier = 0;
     510                if (config::CommonWannier > 4) config::CommonWannier = 4;
     511        }
     512        if(!ParseForParameter(verbose,file,"SawtoothStart", 0, 1, 1, double_type, &(config::SawtoothStart), 1, optional)) {
     513                config::SawtoothStart = 0.01;
     514        } else {
     515                if (config::SawtoothStart < 0.) config::SawtoothStart = 0.;
     516                if (config::SawtoothStart > 1.) config::SawtoothStart = 1.;
     517        }
     518       
     519        ParseForParameter(verbose,file,"MaxOuterStep", 0, 1, 1, int_type, &(config::MaxOuterStep), 1, critical);
     520        if (!ParseForParameter(verbose,file,"Deltat", 0, 1, 1, double_type, &(config::Deltat), 1, optional))
     521                config::Deltat = 1;
     522        ParseForParameter(verbose,file,"OutVisStep", 0, 1, 1, int_type, &(config::OutVisStep), 1, optional);
     523        ParseForParameter(verbose,file,"OutSrcStep", 0, 1, 1, int_type, &(config::OutSrcStep), 1, optional);
     524        ParseForParameter(verbose,file,"TargetTemp", 0, 1, 1, double_type, &(config::TargetTemp), 1, optional);
     525        //ParseForParameter(verbose,file,"Thermostat", 0, 1, 1, int_type, &(config::ScaleTempStep), 1, optional);
     526        if (!ParseForParameter(verbose,file,"EpsWannier", 0, 1, 1, double_type, &(config::EpsWannier), 1, optional))
     527                config::EpsWannier = 1e-8;
     528       
     529        // stop conditions
     530        //if (config::MaxOuterStep <= 0) config::MaxOuterStep = 1;
     531        ParseForParameter(verbose,file,"MaxPsiStep", 0, 1, 1, int_type, &(config::MaxPsiStep), 1, critical);
     532        if (config::MaxPsiStep <= 0) config::MaxPsiStep = 3;
     533       
     534        ParseForParameter(verbose,file,"MaxMinStep", 0, 1, 1, int_type, &(config::MaxMinStep), 1, critical);
     535        ParseForParameter(verbose,file,"RelEpsTotalE", 0, 1, 1, double_type, &(config::RelEpsTotalEnergy), 1, critical);
     536        ParseForParameter(verbose,file,"RelEpsKineticE", 0, 1, 1, double_type, &(config::RelEpsKineticEnergy), 1, critical);
     537        ParseForParameter(verbose,file,"MaxMinStopStep", 0, 1, 1, int_type, &(config::MaxMinStopStep), 1, critical);
     538        ParseForParameter(verbose,file,"MaxMinGapStopStep", 0, 1, 1, int_type, &(config::MaxMinGapStopStep), 1, critical);
     539        if (config::MaxMinStep <= 0) config::MaxMinStep = config::MaxPsiStep;
     540        if (config::MaxMinStopStep < 1) config::MaxMinStopStep = 1;
     541        if (config::MaxMinGapStopStep < 1) config::MaxMinGapStopStep = 1;
     542       
     543        ParseForParameter(verbose,file,"MaxInitMinStep", 0, 1, 1, int_type, &(config::MaxInitMinStep), 1, critical);
     544        ParseForParameter(verbose,file,"InitRelEpsTotalE", 0, 1, 1, double_type, &(config::InitRelEpsTotalEnergy), 1, critical);
     545        ParseForParameter(verbose,file,"InitRelEpsKineticE", 0, 1, 1, double_type, &(config::InitRelEpsKineticEnergy), 1, critical);
     546        ParseForParameter(verbose,file,"InitMaxMinStopStep", 0, 1, 1, int_type, &(config::InitMaxMinStopStep), 1, critical);
     547        ParseForParameter(verbose,file,"InitMaxMinGapStopStep", 0, 1, 1, int_type, &(config::InitMaxMinGapStopStep), 1, critical);
     548        if (config::MaxInitMinStep <= 0) config::MaxInitMinStep = config::MaxPsiStep;
     549        if (config::InitMaxMinStopStep < 1) config::InitMaxMinStopStep = 1;
     550        if (config::InitMaxMinGapStopStep < 1) config::InitMaxMinGapStopStep = 1;
     551       
     552        // Unit cell and magnetic field
     553        ParseForParameter(verbose,file, "BoxLength", 0, 3, 3, lower_trigrid, BoxLength, 1, critical); /* Lattice->RealBasis */
     554        mol->cell_size[0] = BoxLength[0];
     555        mol->cell_size[1] = BoxLength[3];
     556        mol->cell_size[2] = BoxLength[4];
     557        mol->cell_size[3] = BoxLength[6];
     558        mol->cell_size[4] = BoxLength[7];
     559        mol->cell_size[5] = BoxLength[8];
     560        if (1) fprintf(stderr,"\n");
     561
     562        ParseForParameter(verbose,file,"DoPerturbation", 0, 1, 1, int_type, &(config::DoPerturbation), 1, optional);
     563        ParseForParameter(verbose,file,"DoOutNICS", 0, 1, 1, int_type, &(config::DoOutNICS), 1, optional);
     564        if (!ParseForParameter(verbose,file,"DoFullCurrent", 0, 1, 1, int_type, &(config::DoFullCurrent), 1, optional))
     565                config::DoFullCurrent = 0;
     566        if (config::DoFullCurrent < 0) config::DoFullCurrent = 0;
     567        if (config::DoFullCurrent > 2) config::DoFullCurrent = 2;
     568        if (config::DoOutNICS < 0) config::DoOutNICS = 0;
     569        if (config::DoOutNICS > 2) config::DoOutNICS = 2;
     570        if (config::DoPerturbation == 0) {
     571                config::DoFullCurrent = 0;
     572                config::DoOutNICS = 0;
     573        }
     574
     575        ParseForParameter(verbose,file,"ECut", 0, 1, 1, double_type, &(config::ECut), 1, critical);
     576        ParseForParameter(verbose,file,"MaxLevel", 0, 1, 1, int_type, &(config::MaxLevel), 1, critical);
     577        ParseForParameter(verbose,file,"Level0Factor", 0, 1, 1, int_type, &(config::Lev0Factor), 1, critical);
     578        if (config::Lev0Factor < 2) {
     579                config::Lev0Factor = 2;
     580        }
     581        ParseForParameter(verbose,file,"RiemannTensor", 0, 1, 1, int_type, &di, 1, critical);
     582        if (di >= 0 && di < 2) {
     583                config::RiemannTensor = di;
     584        } else {
     585                fprintf(stderr, "0 <= RiemanTensor < 2: 0 UseNotRT, 1 UseRT");
     586                exit(1);
     587        }
     588        switch (config::RiemannTensor) {
     589                case 0: //UseNoRT
     590                        if (config::MaxLevel < 2) {
     591                                config::MaxLevel = 2;
     592                        }
     593                        config::LevRFactor = 2;
     594                        config::RTActualUse = 0;
     595                        break;
     596                case 1: // UseRT
     597                        if (config::MaxLevel < 3) {
     598                                config::MaxLevel = 3;
     599                        }
     600                        ParseForParameter(verbose,file,"RiemannLevel", 0, 1, 1, int_type, &(config::RiemannLevel), 1, critical);
     601                        if (config::RiemannLevel < 2) {
     602                                config::RiemannLevel = 2;
     603                        }
     604                        if (config::RiemannLevel > config::MaxLevel-1) {
     605                                config::RiemannLevel = config::MaxLevel-1;
     606                        }
     607                        ParseForParameter(verbose,file,"LevRFactor", 0, 1, 1, int_type, &(config::LevRFactor), 1, critical);
     608                        if (config::LevRFactor < 2) {
     609                                config::LevRFactor = 2;
     610                        }
     611                        config::Lev0Factor = 2;
     612                        config::RTActualUse = 2;
     613                        break;
     614        }
     615        ParseForParameter(verbose,file,"PsiType", 0, 1, 1, int_type, &di, 1, critical);
     616        if (di >= 0 && di < 2) {
     617                config::PsiType = di;
     618        } else {
     619                fprintf(stderr, "0 <= PsiType < 2: 0 UseSpinDouble, 1 UseSpinUpDown");
     620                exit(1);
     621        }
     622        switch (config::PsiType) {
     623        case 0: // SpinDouble
     624                ParseForParameter(verbose,file,"MaxPsiDouble", 0, 1, 1, int_type, &(config::MaxPsiDouble), 1, critical);
     625                ParseForParameter(verbose,file,"AddPsis", 0, 1, 1, int_type, &(config::AddPsis), 1, optional);
     626                break;
     627        case 1: // SpinUpDown
     628                if (config::ProcPEGamma % 2) config::ProcPEGamma*=2;
     629                ParseForParameter(verbose,file,"PsiMaxNoUp", 0, 1, 1, int_type, &(config::PsiMaxNoUp), 1, critical);
     630                ParseForParameter(verbose,file,"PsiMaxNoDown", 0, 1, 1, int_type, &(config::PsiMaxNoDown), 1, critical);
     631                ParseForParameter(verbose,file,"AddPsis", 0, 1, 1, int_type, &(config::AddPsis), 1, optional);
     632                break;
     633        }
     634       
     635        // IonsInitRead
     636       
     637        ParseForParameter(verbose,file,"RCut", 0, 1, 1, double_type, &(config::RCut), 1, critical);
     638        ParseForParameter(verbose,file,"IsAngstroem", 0, 1, 1, int_type, &(config::IsAngstroem), 1, critical);
     639        ParseForParameter(verbose,file,"MaxTypes", 0, 1, 1, int_type, &(config::MaxTypes), 1, critical);
     640        if (!ParseForParameter(verbose,file,"RelativeCoord", 0, 1, 1, int_type, &(config::RelativeCoord) , 1, optional))
     641                config::RelativeCoord = 0;
     642        if (!ParseForParameter(verbose,file,"StructOpt", 0, 1, 1, int_type, &(config::StructOpt), 1, optional))
     643                config::StructOpt = 0;
     644        if (MaxTypes == 0) {
     645                cerr << "There are no atoms according to MaxTypes in this config file." << endl;
     646        } else {
     647                // prescan number of ions per type
     648                cout << Verbose(0) << "Prescanning ions per type: " << endl;
     649                for (int i=0; i < config::MaxTypes; i++) {
     650                        sprintf(name,"Ion_Type%i",i+1);
     651                        ParseForParameter(verbose,file, (const char*)name, 0, 1, 1, int_type, &No[i], 1, critical);
     652                        ParseForParameter(verbose,file, name, 0, 2, 1, int_type, &Z, 1, critical);
     653                        elementhash[i] = periode->FindElement(Z);
     654                        cout << Verbose(1) << i << ". Z = " << elementhash[i]->Z << " with " << No[i] << " ions." << endl;
     655                }
     656                int repetition = 0; // which repeated keyword shall be read
     657       
     658                map<int, atom *> AtomList[config::MaxTypes];
     659                if (!FastParsing) {
     660                        // parse in trajectories
     661                        bool status = true;
     662                        atom *neues = NULL;
     663                        while (status) {
     664                                cout << "Currently parsing MD step " << repetition << "." << endl;
     665                                for (int i=0; i < config::MaxTypes; i++) {
     666                                        sprintf(name,"Ion_Type%i",i+1);
     667                                        for(int j=0;j<No[i];j++) {
     668                                                sprintf(keyword,"%s_%i",name, j+1);
     669                                                if (repetition == 0) {
     670                                                        neues = new atom();
     671                                                        AtomList[i][j] = neues;
     672                                                        neues->type = elementhash[i]; // find element type
     673                                                        mol->AddAtom(neues);
     674                                                } else
     675                                                        neues = AtomList[i][j];
     676                                                status = (status &&
     677                                                                                ParseForParameter(verbose,file, keyword, 0, 1, 1, double_type, &neues->x.x[0], 1, (repetition == 0) ? critical : optional) &&
     678                                                                                ParseForParameter(verbose,file, keyword, 0, 2, 1, double_type, &neues->x.x[1], 1, (repetition == 0) ? critical : optional) &&
     679                                                                                ParseForParameter(verbose,file, keyword, 0, 3, 1, double_type, &neues->x.x[2], 1, (repetition == 0) ? critical : optional) &&
     680                                                                                ParseForParameter(verbose,file, keyword, 0, 4, 1, int_type, &neues->FixedIon, 1, (repetition == 0) ? critical : optional));
     681                                                if (!status) break;
     682               
     683                                                // check size of vectors
     684                                                if (mol->Trajectories[neues].R.size() <= (unsigned int)(repetition)) {
     685                                                        //cout << "Increasing size for trajectory array of " << keyword << " to " << (repetition+10) << "." << endl;
     686                                                        mol->Trajectories[neues].R.resize(repetition+10);
     687                                                        mol->Trajectories[neues].U.resize(repetition+10);
     688                                                        mol->Trajectories[neues].F.resize(repetition+10);
     689                                                }
     690                                       
     691                                                // put into trajectories list
     692                                                for (int d=0;d<NDIM;d++)
     693                                                        mol->Trajectories[neues].R.at(repetition).x[d] = neues->x.x[d];
     694                                               
     695                                                // parse velocities if present
     696                                                if(!ParseForParameter(verbose,file, keyword, 0, 5, 1, double_type, &neues->v.x[0], 1,optional))
     697                                                        neues->v.x[0] = 0.;
     698                                                if(!ParseForParameter(verbose,file, keyword, 0, 6, 1, double_type, &neues->v.x[1], 1,optional))
     699                                                        neues->v.x[1] = 0.;
     700                                                if(!ParseForParameter(verbose,file, keyword, 0, 7, 1, double_type, &neues->v.x[2], 1,optional))
     701                                                        neues->v.x[2] = 0.;
     702                                                for (int d=0;d<NDIM;d++)
     703                                                        mol->Trajectories[neues].U.at(repetition).x[d] = neues->v.x[d];
     704                       
     705                                                // parse forces if present
     706                                                if(!ParseForParameter(verbose,file, keyword, 0, 8, 1, double_type, &value[0], 1,optional))
     707                                                        value[0] = 0.;
     708                                                if(!ParseForParameter(verbose,file, keyword, 0, 9, 1, double_type, &value[1], 1,optional))
     709                                                        value[1] = 0.;
     710                                                if(!ParseForParameter(verbose,file, keyword, 1, 10, 1, double_type, &value[2], 1,optional))
     711                                                        value[2] = 0.;
     712                                                for (int d=0;d<NDIM;d++)
     713                                                        mol->Trajectories[neues].F.at(repetition).x[d] = value[d];
     714       
     715        //                                              cout << "Parsed position of step " << (repetition) << ": (";
     716        //                                              for (int d=0;d<NDIM;d++)
     717        //                                                      cout << mol->Trajectories[neues].R.at(repetition).x[d] << " ";                                  // next step
     718        //                                              cout << ")\t(";
     719        //                                              for (int d=0;d<NDIM;d++)
     720        //                                                      cout << mol->Trajectories[neues].U.at(repetition).x[d] << " ";                                  // next step
     721        //                                              cout << ")\t(";
     722        //                                              for (int d=0;d<NDIM;d++)
     723        //                                                      cout << mol->Trajectories[neues].F.at(repetition).x[d] << " ";                                  // next step
     724        //                                              cout << ")" << endl;
     725                                        }
     726                                }
     727                                repetition++;
     728                        }
     729                        repetition--;
     730                        cout << "Found " << repetition << " trajectory steps." << endl;
     731                        mol->MDSteps = repetition;
     732                } else {
     733                        // find the maximum number of MD steps so that we may parse last one (Ion_Type1_1 must always be present, because is the first atom)
     734                        repetition = 0;
     735                        while ( ParseForParameter(verbose,file, "Ion_Type1_1", 0, 1, 1, double_type, &value[0], repetition, (repetition == 0) ? critical : optional) &&
     736                                                        ParseForParameter(verbose,file, "Ion_Type1_1", 0, 2, 1, double_type, &value[1], repetition, (repetition == 0) ? critical : optional) &&
     737                                                        ParseForParameter(verbose,file, "Ion_Type1_1", 0, 3, 1, double_type, &value[2], repetition, (repetition == 0) ? critical : optional))
     738                                repetition++;
     739                        cout << "I found " << repetition << " times the keyword Ion_Type1_1." << endl;
     740                        // parse in molecule coordinates
     741                        for (int i=0; i < config::MaxTypes; i++) {
     742                                sprintf(name,"Ion_Type%i",i+1);
     743                                for(int j=0;j<No[i];j++) {
     744                                        sprintf(keyword,"%s_%i",name, j+1);
     745                                        atom *neues = new atom();
     746                                        // then parse for each atom the coordinates as often as present
     747                                        ParseForParameter(verbose,file, keyword, 0, 1, 1, double_type, &neues->x.x[0], repetition,critical);
     748                                        ParseForParameter(verbose,file, keyword, 0, 2, 1, double_type, &neues->x.x[1], repetition,critical);
     749                                        ParseForParameter(verbose,file, keyword, 0, 3, 1, double_type, &neues->x.x[2], repetition,critical);
     750                                        ParseForParameter(verbose,file, keyword, 0, 4, 1, int_type, &neues->FixedIon, repetition,critical);
     751                                        if(!ParseForParameter(verbose,file, keyword, 0, 5, 1, double_type, &neues->v.x[0], repetition,optional))
     752                                                neues->v.x[0] = 0.;
     753                                        if(!ParseForParameter(verbose,file, keyword, 0, 6, 1, double_type, &neues->v.x[1], repetition,optional))
     754                                                neues->v.x[1] = 0.;
     755                                        if(!ParseForParameter(verbose,file, keyword, 0, 7, 1, double_type, &neues->v.x[2], repetition,optional))
     756                                                neues->v.x[2] = 0.;
     757                                        // here we don't care if forces are present (last in trajectories is always equal to current position)
     758                                        neues->type = elementhash[i]; // find element type
     759                                        mol->AddAtom(neues);
     760                                }
     761                        }
     762                }
     763        }
     764        file->close();
     765        delete(file);
    766766};
    767767
     
    773773void config::LoadOld(char *filename, periodentafel *periode, molecule *mol)
    774774{
    775   ifstream *file = new ifstream(filename);
    776   if (file == NULL) {
    777     cerr << "ERROR: config file " << filename << " missing!" << endl;
    778     return;
    779   }
    780   RetrieveConfigPathAndName(filename);
    781   // ParseParameters
    782  
    783   /* Oeffne Hauptparameterdatei */
    784   int l, i, di;
    785   double a,b;
    786   double BoxLength[9];
    787   string zeile;
    788   string dummy;
    789   element *elementhash[128];
    790   int Z, No, AtomNo, found;
    791   int verbose = 0;
    792  
    793   /* Namen einlesen */
    794 
    795   ParseForParameter(verbose,file, "mainname", 0, 1, 1, string_type, (config::mainname), 1, critical);
    796   ParseForParameter(verbose,file, "defaultpath", 0, 1, 1, string_type, (config::defaultpath), 1, critical);
    797   ParseForParameter(verbose,file, "pseudopotpath", 0, 1, 1, string_type, (config::pseudopotpath), 1, critical);
    798   ParseForParameter(verbose,file, "ProcsGammaPsi", 0, 1, 1, int_type, &(config::ProcPEGamma), 1, critical);
    799   ParseForParameter(verbose,file, "ProcsGammaPsi", 0, 2, 1, int_type, &(config::ProcPEPsi), 1, critical);
    800   config::Seed = 1;
    801   config::DoOutOrbitals = 0;
    802   ParseForParameter(verbose,file,"DoOutVis", 0, 1, 1, int_type, &(config::DoOutVis), 1, critical);
    803   if (config::DoOutVis < 0) config::DoOutVis = 0;
    804   if (config::DoOutVis > 1) config::DoOutVis = 1;
    805   config::VectorPlane = -1;
    806   config::VectorCut = 0.;
    807   ParseForParameter(verbose,file,"DoOutMes", 0, 1, 1, int_type, &(config::DoOutMes), 1, critical);
    808   if (config::DoOutMes < 0) config::DoOutMes = 0;
    809   if (config::DoOutMes > 1) config::DoOutMes = 1;
    810   config::DoOutCurrent = 0;
    811   ParseForParameter(verbose,file,"AddGramSch", 0, 1, 1, int_type, &(config::UseAddGramSch), 1, critical);
    812   if (config::UseAddGramSch < 0) config::UseAddGramSch = 0;
    813   if (config::UseAddGramSch > 2) config::UseAddGramSch = 2;
    814   config::CommonWannier = 0;
    815   config::SawtoothStart = 0.01;
    816 
    817   ParseForParameter(verbose,file,"MaxOuterStep", 0, 1, 1, double_type, &(config::MaxOuterStep), 1, critical);
    818   ParseForParameter(verbose,file,"Deltat", 0, 1, 1, double_type, &(config::Deltat), 1, optional);
    819   ParseForParameter(verbose,file,"VisOuterStep", 0, 1, 1, int_type, &(config::OutVisStep), 1, optional);
    820   ParseForParameter(verbose,file,"VisSrcOuterStep", 0, 1, 1, int_type, &(config::OutSrcStep), 1, optional);
    821   ParseForParameter(verbose,file,"TargetTemp", 0, 1, 1, double_type, &(config::TargetTemp), 1, optional);
    822   ParseForParameter(verbose,file,"ScaleTempStep", 0, 1, 1, int_type, &(config::ScaleTempStep), 1, optional);
    823   config::EpsWannier = 1e-8;
    824  
    825   // stop conditions
    826   //if (config::MaxOuterStep <= 0) config::MaxOuterStep = 1;
    827   ParseForParameter(verbose,file,"MaxPsiStep", 0, 1, 1, int_type, &(config::MaxPsiStep), 1, critical);
    828   if (config::MaxPsiStep <= 0) config::MaxPsiStep = 3;
    829  
    830   ParseForParameter(verbose,file,"MaxMinStep", 0, 1, 1, int_type, &(config::MaxMinStep), 1, critical);
    831   ParseForParameter(verbose,file,"MaxMinStep", 0, 2, 1, double_type, &(config::RelEpsTotalEnergy), 1, critical);
    832   ParseForParameter(verbose,file,"MaxMinStep", 0, 3, 1, double_type, &(config::RelEpsKineticEnergy), 1, critical);
    833   ParseForParameter(verbose,file,"MaxMinStep", 0, 4, 1, int_type, &(config::MaxMinStopStep), 1, critical);
    834   if (config::MaxMinStep <= 0) config::MaxMinStep = config::MaxPsiStep;
    835   if (config::MaxMinStopStep < 1) config::MaxMinStopStep = 1;
    836   config::MaxMinGapStopStep = 1;
    837  
    838   ParseForParameter(verbose,file,"MaxInitMinStep", 0, 1, 1, int_type, &(config::MaxInitMinStep), 1, critical);
    839   ParseForParameter(verbose,file,"MaxInitMinStep", 0, 2, 1, double_type, &(config::InitRelEpsTotalEnergy), 1, critical);
    840   ParseForParameter(verbose,file,"MaxInitMinStep", 0, 3, 1, double_type, &(config::InitRelEpsKineticEnergy), 1, critical);
    841   ParseForParameter(verbose,file,"MaxInitMinStep", 0, 4, 1, int_type, &(config::InitMaxMinStopStep), 1, critical);
    842   if (config::MaxInitMinStep <= 0) config::MaxInitMinStep = config::MaxPsiStep;
    843   if (config::InitMaxMinStopStep < 1) config::InitMaxMinStopStep = 1;
    844   config::InitMaxMinGapStopStep = 1;
    845 
    846   ParseForParameter(verbose,file, "BoxLength", 0, 3, 3, lower_trigrid, BoxLength, 1, critical); /* Lattice->RealBasis */
    847   mol->cell_size[0] = BoxLength[0];
    848   mol->cell_size[1] = BoxLength[3];
    849   mol->cell_size[2] = BoxLength[4];
    850   mol->cell_size[3] = BoxLength[6];
    851   mol->cell_size[4] = BoxLength[7];
    852   mol->cell_size[5] = BoxLength[8];
    853   if (1) fprintf(stderr,"\n");
    854   config::DoPerturbation = 0;
    855   config::DoFullCurrent = 0;
    856 
    857   ParseForParameter(verbose,file,"ECut", 0, 1, 1, double_type, &(config::ECut), 1, critical);
    858   ParseForParameter(verbose,file,"MaxLevel", 0, 1, 1, int_type, &(config::MaxLevel), 1, critical);
    859   ParseForParameter(verbose,file,"Level0Factor", 0, 1, 1, int_type, &(config::Lev0Factor), 1, critical);
    860   if (config::Lev0Factor < 2) {
    861     config::Lev0Factor = 2;
    862   }
    863   ParseForParameter(verbose,file,"RiemannTensor", 0, 1, 1, int_type, &di, 1, critical);
    864   if (di >= 0 && di < 2) {
    865     config::RiemannTensor = di;
    866   } else {
    867     fprintf(stderr, "0 <= RiemanTensor < 2: 0 UseNotRT, 1 UseRT");
    868     exit(1);
    869   }
    870   switch (config::RiemannTensor) {
    871     case 0: //UseNoRT
    872       if (config::MaxLevel < 2) {
    873         config::MaxLevel = 2;
    874       }
    875       config::LevRFactor = 2;
    876       config::RTActualUse = 0;
    877       break;
    878     case 1: // UseRT
    879       if (config::MaxLevel < 3) {
    880         config::MaxLevel = 3;
    881       }
    882       ParseForParameter(verbose,file,"RiemannLevel", 0, 1, 1, int_type, &(config::RiemannLevel), 1, critical);
    883       if (config::RiemannLevel < 2) {
    884         config::RiemannLevel = 2;
    885       }
    886       if (config::RiemannLevel > config::MaxLevel-1) {
    887         config::RiemannLevel = config::MaxLevel-1;
    888       }
    889       ParseForParameter(verbose,file,"LevRFactor", 0, 1, 1, int_type, &(config::LevRFactor), 1, critical);
    890       if (config::LevRFactor < 2) {
    891         config::LevRFactor = 2;
    892       }
    893       config::Lev0Factor = 2;
    894       config::RTActualUse = 2;
    895       break;
    896   }
    897   ParseForParameter(verbose,file,"PsiType", 0, 1, 1, int_type, &di, 1, critical);
    898   if (di >= 0 && di < 2) {
    899     config::PsiType = di;
    900   } else {
    901     fprintf(stderr, "0 <= PsiType < 2: 0 UseSpinDouble, 1 UseSpinUpDown");
    902     exit(1);
    903   }
    904   switch (config::PsiType) {
    905   case 0: // SpinDouble
    906     ParseForParameter(verbose,file,"MaxPsiDouble", 0, 1, 1, int_type, &(config::MaxPsiDouble), 1, critical);
    907     config::AddPsis = 0;
    908     break;
    909   case 1: // SpinUpDown
    910     if (config::ProcPEGamma % 2) config::ProcPEGamma*=2;
    911     ParseForParameter(verbose,file,"MaxPsiUp", 0, 1, 1, int_type, &(config::PsiMaxNoUp), 1, critical);
    912     ParseForParameter(verbose,file,"MaxPsiDown", 0, 1, 1, int_type, &(config::PsiMaxNoDown), 1, critical);
    913     config::AddPsis = 0;
    914     break;
    915   }
    916  
    917   // IonsInitRead
    918  
    919   ParseForParameter(verbose,file,"RCut", 0, 1, 1, double_type, &(config::RCut), 1, critical);
    920   ParseForParameter(verbose,file,"IsAngstroem", 0, 1, 1, int_type, &(config::IsAngstroem), 1, critical);
    921   config::RelativeCoord = 0;
    922   config::StructOpt = 0;
    923 
    924   // Routine from builder.cpp
    925  
    926  
    927   for (i=MAX_ELEMENTS;i--;)
    928     elementhash[i] = NULL;
    929   cout << Verbose(0) << "Parsing Ions ..." << endl;
    930   No=0;
    931   found = 0;
    932   while (getline(*file,zeile,'\n')) {
    933     if (zeile.find("Ions_Data") == 0) {
    934       cout << Verbose(1) << "found Ions_Data...begin parsing" << endl;
    935       found ++;
    936     }
    937     if (found > 0) {
    938       if (zeile.find("Ions_Data") == 0)
    939         getline(*file,zeile,'\n'); // read next line and parse this one
    940       istringstream input(zeile);
    941       input >> AtomNo;  // number of atoms
    942       input >> Z;      // atomic number
    943       input >> a;
    944       input >> l;
    945       input >> l;
    946       input >> b;    // element mass
    947       elementhash[No] = periode->FindElement(Z);
    948       cout << Verbose(1) << "AtomNo: " << AtomNo << "\tZ: " << Z << "\ta:" << a << "\tl:"  << l << "\b:" << b << "\tElement:" << elementhash[No] << "\t:" << endl;
    949       for(i=0;i<AtomNo;i++) {
    950         if (!getline(*file,zeile,'\n')) {// parse on and on
    951           cout << Verbose(2) << "Error: Too few items in ionic list of element" << elementhash[No] << "." << endl << "Exiting." << endl;
    952           // return 1;
    953         } else {
    954           //cout << Verbose(2) << "Reading line: " << zeile << endl;
    955         }
    956         istringstream input2(zeile);
    957         atom *neues = new atom();
    958         input2 >> neues->x.x[0]; // x
    959         input2 >> neues->x.x[1]; // y
    960         input2 >> neues->x.x[2]; // z
    961         input2 >> l;
    962         neues->type = elementhash[No]; // find element type
    963         mol->AddAtom(neues);
    964       }
    965       No++;
    966     }
    967   } 
    968   file->close();
    969   delete(file);
     775        ifstream *file = new ifstream(filename);
     776        if (file == NULL) {
     777                cerr << "ERROR: config file " << filename << " missing!" << endl;
     778                return;
     779        }
     780        RetrieveConfigPathAndName(filename);
     781        // ParseParameters
     782       
     783        /* Oeffne Hauptparameterdatei */
     784        int l, i, di;
     785        double a,b;
     786        double BoxLength[9];
     787        string zeile;
     788        string dummy;
     789        element *elementhash[128];
     790        int Z, No, AtomNo, found;
     791        int verbose = 0;
     792       
     793        /* Namen einlesen */
     794
     795        ParseForParameter(verbose,file, "mainname", 0, 1, 1, string_type, (config::mainname), 1, critical);
     796        ParseForParameter(verbose,file, "defaultpath", 0, 1, 1, string_type, (config::defaultpath), 1, critical);
     797        ParseForParameter(verbose,file, "pseudopotpath", 0, 1, 1, string_type, (config::pseudopotpath), 1, critical);
     798        ParseForParameter(verbose,file, "ProcsGammaPsi", 0, 1, 1, int_type, &(config::ProcPEGamma), 1, critical);
     799        ParseForParameter(verbose,file, "ProcsGammaPsi", 0, 2, 1, int_type, &(config::ProcPEPsi), 1, critical);
     800        config::Seed = 1;
     801        config::DoOutOrbitals = 0;
     802        ParseForParameter(verbose,file,"DoOutVis", 0, 1, 1, int_type, &(config::DoOutVis), 1, critical);
     803        if (config::DoOutVis < 0) config::DoOutVis = 0;
     804        if (config::DoOutVis > 1) config::DoOutVis = 1;
     805        config::VectorPlane = -1;
     806        config::VectorCut = 0.;
     807        ParseForParameter(verbose,file,"DoOutMes", 0, 1, 1, int_type, &(config::DoOutMes), 1, critical);
     808        if (config::DoOutMes < 0) config::DoOutMes = 0;
     809        if (config::DoOutMes > 1) config::DoOutMes = 1;
     810        config::DoOutCurrent = 0;
     811        ParseForParameter(verbose,file,"AddGramSch", 0, 1, 1, int_type, &(config::UseAddGramSch), 1, critical);
     812        if (config::UseAddGramSch < 0) config::UseAddGramSch = 0;
     813        if (config::UseAddGramSch > 2) config::UseAddGramSch = 2;
     814        config::CommonWannier = 0;
     815        config::SawtoothStart = 0.01;
     816
     817        ParseForParameter(verbose,file,"MaxOuterStep", 0, 1, 1, double_type, &(config::MaxOuterStep), 1, critical);
     818        ParseForParameter(verbose,file,"Deltat", 0, 1, 1, double_type, &(config::Deltat), 1, optional);
     819        ParseForParameter(verbose,file,"VisOuterStep", 0, 1, 1, int_type, &(config::OutVisStep), 1, optional);
     820        ParseForParameter(verbose,file,"VisSrcOuterStep", 0, 1, 1, int_type, &(config::OutSrcStep), 1, optional);
     821        ParseForParameter(verbose,file,"TargetTemp", 0, 1, 1, double_type, &(config::TargetTemp), 1, optional);
     822        ParseForParameter(verbose,file,"ScaleTempStep", 0, 1, 1, int_type, &(config::ScaleTempStep), 1, optional);
     823        config::EpsWannier = 1e-8;
     824       
     825        // stop conditions
     826        //if (config::MaxOuterStep <= 0) config::MaxOuterStep = 1;
     827        ParseForParameter(verbose,file,"MaxPsiStep", 0, 1, 1, int_type, &(config::MaxPsiStep), 1, critical);
     828        if (config::MaxPsiStep <= 0) config::MaxPsiStep = 3;
     829       
     830        ParseForParameter(verbose,file,"MaxMinStep", 0, 1, 1, int_type, &(config::MaxMinStep), 1, critical);
     831        ParseForParameter(verbose,file,"MaxMinStep", 0, 2, 1, double_type, &(config::RelEpsTotalEnergy), 1, critical);
     832        ParseForParameter(verbose,file,"MaxMinStep", 0, 3, 1, double_type, &(config::RelEpsKineticEnergy), 1, critical);
     833        ParseForParameter(verbose,file,"MaxMinStep", 0, 4, 1, int_type, &(config::MaxMinStopStep), 1, critical);
     834        if (config::MaxMinStep <= 0) config::MaxMinStep = config::MaxPsiStep;
     835        if (config::MaxMinStopStep < 1) config::MaxMinStopStep = 1;
     836        config::MaxMinGapStopStep = 1;
     837       
     838        ParseForParameter(verbose,file,"MaxInitMinStep", 0, 1, 1, int_type, &(config::MaxInitMinStep), 1, critical);
     839        ParseForParameter(verbose,file,"MaxInitMinStep", 0, 2, 1, double_type, &(config::InitRelEpsTotalEnergy), 1, critical);
     840        ParseForParameter(verbose,file,"MaxInitMinStep", 0, 3, 1, double_type, &(config::InitRelEpsKineticEnergy), 1, critical);
     841        ParseForParameter(verbose,file,"MaxInitMinStep", 0, 4, 1, int_type, &(config::InitMaxMinStopStep), 1, critical);
     842        if (config::MaxInitMinStep <= 0) config::MaxInitMinStep = config::MaxPsiStep;
     843        if (config::InitMaxMinStopStep < 1) config::InitMaxMinStopStep = 1;
     844        config::InitMaxMinGapStopStep = 1;
     845
     846        ParseForParameter(verbose,file, "BoxLength", 0, 3, 3, lower_trigrid, BoxLength, 1, critical); /* Lattice->RealBasis */
     847        mol->cell_size[0] = BoxLength[0];
     848        mol->cell_size[1] = BoxLength[3];
     849        mol->cell_size[2] = BoxLength[4];
     850        mol->cell_size[3] = BoxLength[6];
     851        mol->cell_size[4] = BoxLength[7];
     852        mol->cell_size[5] = BoxLength[8];
     853        if (1) fprintf(stderr,"\n");
     854        config::DoPerturbation = 0;
     855        config::DoFullCurrent = 0;
     856
     857        ParseForParameter(verbose,file,"ECut", 0, 1, 1, double_type, &(config::ECut), 1, critical);
     858        ParseForParameter(verbose,file,"MaxLevel", 0, 1, 1, int_type, &(config::MaxLevel), 1, critical);
     859        ParseForParameter(verbose,file,"Level0Factor", 0, 1, 1, int_type, &(config::Lev0Factor), 1, critical);
     860        if (config::Lev0Factor < 2) {
     861                config::Lev0Factor = 2;
     862        }
     863        ParseForParameter(verbose,file,"RiemannTensor", 0, 1, 1, int_type, &di, 1, critical);
     864        if (di >= 0 && di < 2) {
     865                config::RiemannTensor = di;
     866        } else {
     867                fprintf(stderr, "0 <= RiemanTensor < 2: 0 UseNotRT, 1 UseRT");
     868                exit(1);
     869        }
     870        switch (config::RiemannTensor) {
     871                case 0: //UseNoRT
     872                        if (config::MaxLevel < 2) {
     873                                config::MaxLevel = 2;
     874                        }
     875                        config::LevRFactor = 2;
     876                        config::RTActualUse = 0;
     877                        break;
     878                case 1: // UseRT
     879                        if (config::MaxLevel < 3) {
     880                                config::MaxLevel = 3;
     881                        }
     882                        ParseForParameter(verbose,file,"RiemannLevel", 0, 1, 1, int_type, &(config::RiemannLevel), 1, critical);
     883                        if (config::RiemannLevel < 2) {
     884                                config::RiemannLevel = 2;
     885                        }
     886                        if (config::RiemannLevel > config::MaxLevel-1) {
     887                                config::RiemannLevel = config::MaxLevel-1;
     888                        }
     889                        ParseForParameter(verbose,file,"LevRFactor", 0, 1, 1, int_type, &(config::LevRFactor), 1, critical);
     890                        if (config::LevRFactor < 2) {
     891                                config::LevRFactor = 2;
     892                        }
     893                        config::Lev0Factor = 2;
     894                        config::RTActualUse = 2;
     895                        break;
     896        }
     897        ParseForParameter(verbose,file,"PsiType", 0, 1, 1, int_type, &di, 1, critical);
     898        if (di >= 0 && di < 2) {
     899                config::PsiType = di;
     900        } else {
     901                fprintf(stderr, "0 <= PsiType < 2: 0 UseSpinDouble, 1 UseSpinUpDown");
     902                exit(1);
     903        }
     904        switch (config::PsiType) {
     905        case 0: // SpinDouble
     906                ParseForParameter(verbose,file,"MaxPsiDouble", 0, 1, 1, int_type, &(config::MaxPsiDouble), 1, critical);
     907                config::AddPsis = 0;
     908                break;
     909        case 1: // SpinUpDown
     910                if (config::ProcPEGamma % 2) config::ProcPEGamma*=2;
     911                ParseForParameter(verbose,file,"MaxPsiUp", 0, 1, 1, int_type, &(config::PsiMaxNoUp), 1, critical);
     912                ParseForParameter(verbose,file,"MaxPsiDown", 0, 1, 1, int_type, &(config::PsiMaxNoDown), 1, critical);
     913                config::AddPsis = 0;
     914                break;
     915        }
     916       
     917        // IonsInitRead
     918       
     919        ParseForParameter(verbose,file,"RCut", 0, 1, 1, double_type, &(config::RCut), 1, critical);
     920        ParseForParameter(verbose,file,"IsAngstroem", 0, 1, 1, int_type, &(config::IsAngstroem), 1, critical);
     921        config::RelativeCoord = 0;
     922        config::StructOpt = 0;
     923
     924        // Routine from builder.cpp
     925       
     926       
     927        for (i=MAX_ELEMENTS;i--;)
     928                elementhash[i] = NULL;
     929        cout << Verbose(0) << "Parsing Ions ..." << endl;
     930        No=0;
     931        found = 0;
     932        while (getline(*file,zeile,'\n')) {
     933                if (zeile.find("Ions_Data") == 0) {
     934                        cout << Verbose(1) << "found Ions_Data...begin parsing" << endl;
     935                        found ++;
     936                }
     937                if (found > 0) {
     938                        if (zeile.find("Ions_Data") == 0)
     939                                getline(*file,zeile,'\n'); // read next line and parse this one
     940                        istringstream input(zeile);
     941                        input >> AtomNo;        // number of atoms
     942                        input >> Z;                      // atomic number
     943                        input >> a;
     944                        input >> l;
     945                        input >> l;
     946                        input >> b;              // element mass
     947                        elementhash[No] = periode->FindElement(Z);
     948                        cout << Verbose(1) << "AtomNo: " << AtomNo << "\tZ: " << Z << "\ta:" << a << "\tl:"     << l << "\b:" << b << "\tElement:" << elementhash[No] << "\t:" << endl;
     949                        for(i=0;i<AtomNo;i++) {
     950                                if (!getline(*file,zeile,'\n')) {// parse on and on
     951                                        cout << Verbose(2) << "Error: Too few items in ionic list of element" << elementhash[No] << "." << endl << "Exiting." << endl;
     952                                        // return 1;
     953                                } else {
     954                                        //cout << Verbose(2) << "Reading line: " << zeile << endl;
     955                                }
     956                                istringstream input2(zeile);
     957                                atom *neues = new atom();
     958                                input2 >> neues->x.x[0]; // x
     959                                input2 >> neues->x.x[1]; // y
     960                                input2 >> neues->x.x[2]; // z
     961                                input2 >> l;
     962                                neues->type = elementhash[No]; // find element type
     963                                mol->AddAtom(neues);
     964                        }
     965                        No++;
     966                }
     967        }       
     968        file->close();
     969        delete(file);
    970970};
    971971
     
    977977bool config::Save(const char *filename, periodentafel *periode, molecule *mol) const
    978978{
    979   bool result = true;
     979        bool result = true;
    980980        // bring MaxTypes up to date
    981981        mol->CountElements();
    982   ofstream *output = NULL;
    983   output = new ofstream(filename, ios::out);
    984   if (output != NULL) {
    985     *output << "# ParallelCarParinello - main configuration file - created with molecuilder" << endl;
    986     *output << endl;
    987     *output << "mainname\t" << config::mainname << "\t# programm name (for runtime files)" << endl;
    988     *output << "defaultpath\t" << config::defaultpath << "\t# where to put files during runtime" << endl;
    989     *output << "pseudopotpath\t" << config::pseudopotpath << "\t# where to find pseudopotentials" << endl;
    990     *output << endl;
    991     *output << "ProcPEGamma\t" << config::ProcPEGamma << "\t# for parallel computing: share constants" << endl;
    992     *output << "ProcPEPsi\t" << config::ProcPEPsi << "\t# for parallel computing: share wave functions" << endl;
    993     *output << "DoOutVis\t" << config::DoOutVis << "\t# Output data for OpenDX" << endl;
    994     *output << "DoOutMes\t" << config::DoOutMes << "\t# Output data for measurements" << endl;
    995     *output << "DoOutOrbitals\t" << config::DoOutOrbitals << "\t# Output all Orbitals" << endl;
    996     *output << "DoOutCurr\t" << config::DoOutCurrent << "\t# Ouput current density for OpenDx" << endl;
    997     *output << "DoOutNICS\t" << config::DoOutNICS << "\t# Output Nucleus independent current shieldings" << endl;
    998     *output << "DoPerturbation\t" << config::DoPerturbation << "\t# Do perturbation calculate and determine susceptibility and shielding" << endl;
    999     *output << "DoFullCurrent\t" << config::DoFullCurrent << "\t# Do full perturbation" << endl;
    1000     *output << "CommonWannier\t" << config::CommonWannier << "\t# Put virtual centers at indivual orbits, all common, merged by variance, to grid point, to cell center" << endl;
    1001     *output << "SawtoothStart\t" << config::SawtoothStart << "\t# Absolute value for smooth transition at cell border " << endl;
    1002     *output << "VectorPlane\t" << config::VectorPlane << "\t# Cut plane axis (x, y or z: 0,1,2) for two-dim current vector plot" << endl;
    1003     *output << "VectorCut\t" << config::VectorCut << "\t# Cut plane axis value" << endl;
    1004     *output << "AddGramSch\t" << config::UseAddGramSch << "\t# Additional GramSchmidtOrtogonalization to be safe" << endl;
    1005     *output << "Seed\t\t" << config::Seed << "\t# initial value for random seed for Psi coefficients" << endl;
    1006     *output << endl;
    1007     *output << "MaxOuterStep\t" << config::MaxOuterStep << "\t# number of MolecularDynamics/Structure optimization steps" << endl;
    1008     *output << "Deltat\t" << config::Deltat << "\t# time per MD step" << endl;
    1009     *output << "OutVisStep\t" << config::OutVisStep << "\t# Output visual data every ...th step" << endl;
    1010     *output << "OutSrcStep\t" << config::OutSrcStep << "\t# Output \"restart\" data every ..th step" << endl;
    1011     *output << "TargetTemp\t" << config::TargetTemp << "\t# Target temperature" << endl;
    1012     *output << "MaxPsiStep\t" << config::MaxPsiStep << "\t# number of Minimisation steps per state (0 - default)" << endl;
    1013     *output << "EpsWannier\t" << config::EpsWannier << "\t# tolerance value for spread minimisation of orbitals" << endl;
    1014     *output << endl;
    1015     *output << "# Values specifying when to stop" << endl;
    1016     *output << "MaxMinStep\t" << config::MaxMinStep << "\t# Maximum number of steps" << endl;
    1017     *output << "RelEpsTotalE\t" << config::RelEpsTotalEnergy << "\t# relative change in total energy" << endl;
    1018     *output << "RelEpsKineticE\t" << config::RelEpsKineticEnergy << "\t# relative change in kinetic energy" << endl;
    1019     *output << "MaxMinStopStep\t" << config::MaxMinStopStep << "\t# check every ..th steps" << endl;
    1020     *output << "MaxMinGapStopStep\t" << config::MaxMinGapStopStep << "\t# check every ..th steps" << endl;
    1021     *output << endl;
    1022     *output << "# Values specifying when to stop for INIT, otherwise same as above" << endl;
    1023     *output << "MaxInitMinStep\t" << config::MaxInitMinStep << "\t# Maximum number of steps" << endl;
    1024     *output << "InitRelEpsTotalE\t" << config::InitRelEpsTotalEnergy << "\t# relative change in total energy" << endl;
    1025     *output << "InitRelEpsKineticE\t" << config::InitRelEpsKineticEnergy << "\t# relative change in kinetic energy" << endl;
    1026     *output << "InitMaxMinStopStep\t" << config::InitMaxMinStopStep << "\t# check every ..th steps" << endl;
    1027     *output << "InitMaxMinGapStopStep\t" << config::InitMaxMinGapStopStep << "\t# check every ..th steps" << endl;
    1028     *output << endl;
    1029     *output << "BoxLength\t\t\t# (Length of a unit cell)" << endl;
    1030     *output << mol->cell_size[0] << "\t" << endl;
    1031     *output << mol->cell_size[1] << "\t" << mol->cell_size[2] << "\t" << endl;
    1032     *output << mol->cell_size[3] << "\t" << mol->cell_size[4] << "\t" << mol->cell_size[5] << "\t" << endl;
    1033     // FIXME
    1034     *output << endl;
    1035     *output << "ECut\t\t" << config::ECut << "\t# energy cutoff for discretization in Hartrees" << endl;
    1036     *output << "MaxLevel\t" << config::MaxLevel << "\t# number of different levels in the code, >=2" << endl;
    1037     *output << "Level0Factor\t" << config::Lev0Factor << "\t# factor by which node number increases from S to 0 level" << endl;
    1038     *output << "RiemannTensor\t" << config::RiemannTensor << "\t# (Use metric)" << endl;
    1039     switch (config::RiemannTensor) {
    1040       case 0: //UseNoRT
    1041         break;
    1042       case 1: // UseRT
    1043         *output << "RiemannLevel\t" << config::RiemannLevel << "\t# Number of Riemann Levels" << endl;
    1044         *output << "LevRFactor\t" << config::LevRFactor << "\t# factor by which node number increases from 0 to R level from" << endl;
    1045         break;
    1046     }
    1047     *output << "PsiType\t\t" << config::PsiType << "\t# 0 - doubly occupied, 1 - SpinUp,SpinDown" << endl;
    1048     // write out both types for easier changing afterwards
    1049   //  switch (PsiType) {
    1050   //    case 0:
    1051         *output << "MaxPsiDouble\t" << config::MaxPsiDouble << "\t# here: specifying both maximum number of SpinUp- and -Down-states" << endl;
    1052   //      break;
    1053   //    case 1:
    1054         *output << "PsiMaxNoUp\t" << config::PsiMaxNoUp << "\t# here: specifying maximum number of SpinUp-states" << endl;
    1055         *output << "PsiMaxNoDown\t" << config::PsiMaxNoDown << "\t# here: specifying maximum number of SpinDown-states" << endl;
    1056   //      break;
    1057   //  }
    1058     *output << "AddPsis\t\t" << config::AddPsis << "\t# Additional unoccupied Psis for bandgap determination" << endl;
    1059     *output << endl;
    1060     *output << "RCut\t\t" << config::RCut << "\t# R-cut for the ewald summation" << endl;
    1061     *output << "StructOpt\t" << config::StructOpt << "\t# Do structure optimization beforehand" << endl;
    1062     *output << "IsAngstroem\t" << config::IsAngstroem << "\t# 0 - Bohr, 1 - Angstroem" << endl;
    1063     *output << "RelativeCoord\t" << config::RelativeCoord << "\t# whether ion coordinates are relative (1) or absolute (0)" << endl;
    1064     *output << "MaxTypes\t" << mol->ElementCount <<  "\t# maximum number of different ion types" << endl;
    1065     *output << endl;
    1066     result = result && mol->Checkout(output);
    1067     if (mol->MDSteps <=1 )
    1068       result = result && mol->Output(output);
    1069     else
    1070       result = result && mol->OutputTrajectories(output);
    1071     output->close();
    1072     output->clear();
    1073     delete(output);
    1074     return result;
    1075   } else
    1076     return false;
     982        ofstream *output = NULL;
     983        output = new ofstream(filename, ios::out);
     984        if (output != NULL) {
     985                *output << "# ParallelCarParinello - main configuration file - created with molecuilder" << endl;
     986                *output << endl;
     987                *output << "mainname\t" << config::mainname << "\t# programm name (for runtime files)" << endl;
     988                *output << "defaultpath\t" << config::defaultpath << "\t# where to put files during runtime" << endl;
     989                *output << "pseudopotpath\t" << config::pseudopotpath << "\t# where to find pseudopotentials" << endl;
     990                *output << endl;
     991                *output << "ProcPEGamma\t" << config::ProcPEGamma << "\t# for parallel computing: share constants" << endl;
     992                *output << "ProcPEPsi\t" << config::ProcPEPsi << "\t# for parallel computing: share wave functions" << endl;
     993                *output << "DoOutVis\t" << config::DoOutVis << "\t# Output data for OpenDX" << endl;
     994                *output << "DoOutMes\t" << config::DoOutMes << "\t# Output data for measurements" << endl;
     995                *output << "DoOutOrbitals\t" << config::DoOutOrbitals << "\t# Output all Orbitals" << endl;
     996                *output << "DoOutCurr\t" << config::DoOutCurrent << "\t# Ouput current density for OpenDx" << endl;
     997                *output << "DoOutNICS\t" << config::DoOutNICS << "\t# Output Nucleus independent current shieldings" << endl;
     998                *output << "DoPerturbation\t" << config::DoPerturbation << "\t# Do perturbation calculate and determine susceptibility and shielding" << endl;
     999                *output << "DoFullCurrent\t" << config::DoFullCurrent << "\t# Do full perturbation" << endl;
     1000                *output << "CommonWannier\t" << config::CommonWannier << "\t# Put virtual centers at indivual orbits, all common, merged by variance, to grid point, to cell center" << endl;
     1001                *output << "SawtoothStart\t" << config::SawtoothStart << "\t# Absolute value for smooth transition at cell border " << endl;
     1002                *output << "VectorPlane\t" << config::VectorPlane << "\t# Cut plane axis (x, y or z: 0,1,2) for two-dim current vector plot" << endl;
     1003                *output << "VectorCut\t" << config::VectorCut << "\t# Cut plane axis value" << endl;
     1004                *output << "AddGramSch\t" << config::UseAddGramSch << "\t# Additional GramSchmidtOrtogonalization to be safe" << endl;
     1005                *output << "Seed\t\t" << config::Seed << "\t# initial value for random seed for Psi coefficients" << endl;
     1006                *output << endl;
     1007                *output << "MaxOuterStep\t" << config::MaxOuterStep << "\t# number of MolecularDynamics/Structure optimization steps" << endl;
     1008                *output << "Deltat\t" << config::Deltat << "\t# time per MD step" << endl;
     1009                *output << "OutVisStep\t" << config::OutVisStep << "\t# Output visual data every ...th step" << endl;
     1010                *output << "OutSrcStep\t" << config::OutSrcStep << "\t# Output \"restart\" data every ..th step" << endl;
     1011                *output << "TargetTemp\t" << config::TargetTemp << "\t# Target temperature" << endl;
     1012                *output << "MaxPsiStep\t" << config::MaxPsiStep << "\t# number of Minimisation steps per state (0 - default)" << endl;
     1013                *output << "EpsWannier\t" << config::EpsWannier << "\t# tolerance value for spread minimisation of orbitals" << endl;
     1014                *output << endl;
     1015                *output << "# Values specifying when to stop" << endl;
     1016                *output << "MaxMinStep\t" << config::MaxMinStep << "\t# Maximum number of steps" << endl;
     1017                *output << "RelEpsTotalE\t" << config::RelEpsTotalEnergy << "\t# relative change in total energy" << endl;
     1018                *output << "RelEpsKineticE\t" << config::RelEpsKineticEnergy << "\t# relative change in kinetic energy" << endl;
     1019                *output << "MaxMinStopStep\t" << config::MaxMinStopStep << "\t# check every ..th steps" << endl;
     1020                *output << "MaxMinGapStopStep\t" << config::MaxMinGapStopStep << "\t# check every ..th steps" << endl;
     1021                *output << endl;
     1022                *output << "# Values specifying when to stop for INIT, otherwise same as above" << endl;
     1023                *output << "MaxInitMinStep\t" << config::MaxInitMinStep << "\t# Maximum number of steps" << endl;
     1024                *output << "InitRelEpsTotalE\t" << config::InitRelEpsTotalEnergy << "\t# relative change in total energy" << endl;
     1025                *output << "InitRelEpsKineticE\t" << config::InitRelEpsKineticEnergy << "\t# relative change in kinetic energy" << endl;
     1026                *output << "InitMaxMinStopStep\t" << config::InitMaxMinStopStep << "\t# check every ..th steps" << endl;
     1027                *output << "InitMaxMinGapStopStep\t" << config::InitMaxMinGapStopStep << "\t# check every ..th steps" << endl;
     1028                *output << endl;
     1029                *output << "BoxLength\t\t\t# (Length of a unit cell)" << endl;
     1030                *output << mol->cell_size[0] << "\t" << endl;
     1031                *output << mol->cell_size[1] << "\t" << mol->cell_size[2] << "\t" << endl;
     1032                *output << mol->cell_size[3] << "\t" << mol->cell_size[4] << "\t" << mol->cell_size[5] << "\t" << endl;
     1033                // FIXME
     1034                *output << endl;
     1035                *output << "ECut\t\t" << config::ECut << "\t# energy cutoff for discretization in Hartrees" << endl;
     1036                *output << "MaxLevel\t" << config::MaxLevel << "\t# number of different levels in the code, >=2" << endl;
     1037                *output << "Level0Factor\t" << config::Lev0Factor << "\t# factor by which node number increases from S to 0 level" << endl;
     1038                *output << "RiemannTensor\t" << config::RiemannTensor << "\t# (Use metric)" << endl;
     1039                switch (config::RiemannTensor) {
     1040                        case 0: //UseNoRT
     1041                                break;
     1042                        case 1: // UseRT
     1043                                *output << "RiemannLevel\t" << config::RiemannLevel << "\t# Number of Riemann Levels" << endl;
     1044                                *output << "LevRFactor\t" << config::LevRFactor << "\t# factor by which node number increases from 0 to R level from" << endl;
     1045                                break;
     1046                }
     1047                *output << "PsiType\t\t" << config::PsiType << "\t# 0 - doubly occupied, 1 - SpinUp,SpinDown" << endl;
     1048                // write out both types for easier changing afterwards
     1049        //      switch (PsiType) {
     1050        //              case 0:
     1051                                *output << "MaxPsiDouble\t" << config::MaxPsiDouble << "\t# here: specifying both maximum number of SpinUp- and -Down-states" << endl;
     1052        //                      break;
     1053        //              case 1:
     1054                                *output << "PsiMaxNoUp\t" << config::PsiMaxNoUp << "\t# here: specifying maximum number of SpinUp-states" << endl;
     1055                                *output << "PsiMaxNoDown\t" << config::PsiMaxNoDown << "\t# here: specifying maximum number of SpinDown-states" << endl;
     1056        //                      break;
     1057        //      }
     1058                *output << "AddPsis\t\t" << config::AddPsis << "\t# Additional unoccupied Psis for bandgap determination" << endl;
     1059                *output << endl;
     1060                *output << "RCut\t\t" << config::RCut << "\t# R-cut for the ewald summation" << endl;
     1061                *output << "StructOpt\t" << config::StructOpt << "\t# Do structure optimization beforehand" << endl;
     1062                *output << "IsAngstroem\t" << config::IsAngstroem << "\t# 0 - Bohr, 1 - Angstroem" << endl;
     1063                *output << "RelativeCoord\t" << config::RelativeCoord << "\t# whether ion coordinates are relative (1) or absolute (0)" << endl;
     1064                *output << "MaxTypes\t" << mol->ElementCount << "\t# maximum number of different ion types" << endl;
     1065                *output << endl;
     1066                result = result && mol->Checkout(output);
     1067                if (mol->MDSteps <=1 )
     1068                        result = result && mol->Output(output);
     1069                else
     1070                        result = result && mol->OutputTrajectories(output);
     1071                output->close();
     1072                output->clear();
     1073                delete(output);
     1074                return result;
     1075        } else
     1076                return false;
    10771077};
    10781078
     
    10841084bool config::SaveMPQC(const char *filename, molecule *mol) const
    10851085{
    1086   int ElementNo = 0;
    1087   int AtomNo;
    1088   atom *Walker = NULL;
    1089   element *runner = NULL;
    1090   Vector *center = NULL;
    1091   ofstream *output = NULL;
    1092   stringstream *fname = NULL;
    1093  
    1094   // first without hessian
    1095   fname = new stringstream;
    1096   *fname << filename << ".in";
    1097   output = new ofstream(fname->str().c_str(), ios::out);
    1098   *output << "% Created by MoleCuilder" << endl;
    1099   *output << "mpqc: (" << endl;
    1100   *output << "\tsavestate = no" << endl;
    1101   *output << "\tdo_gradient = yes" << endl;
    1102   *output << "\tmole<CLHF>: (" << endl;
    1103   *output << "\t\tmaxiter = 200" << endl;
    1104   *output << "\t\tbasis = $:basis" << endl;
    1105   *output << "\t\tmolecule = $:molecule" << endl;
    1106   *output << "\t)" << endl;
    1107   *output << ")" << endl;
    1108   *output << "molecule<Molecule>: (" << endl;
    1109   *output << "\tunit = " << (IsAngstroem ? "angstrom" : "bohr" ) << endl;
    1110   *output << "\t{ atoms geometry } = {" << endl;
    1111   center = mol->DetermineCenterOfAll(output);
    1112   // output of atoms
    1113   runner = mol->elemente->start;
    1114   while (runner->next != mol->elemente->end) { // go through every element
    1115     runner = runner->next;
    1116     if (mol->ElementsInMolecule[runner->Z]) { // if this element got atoms
    1117       ElementNo++;
    1118       AtomNo = 0;
    1119       Walker = mol->start;
    1120       while (Walker->next != mol->end) { // go through every atom of this element
    1121         Walker = Walker->next;
    1122         if (Walker->type == runner) { // if this atom fits to element
    1123           AtomNo++;
    1124           *output << "\t\t" << Walker->type->symbol << " [ " << Walker->x.x[0]-center->x[0] << "\t" << Walker->x.x[1]-center->x[1] << "\t" << Walker->x.x[2]-center->x[2] << " ]" << endl;
    1125         }
    1126       }
    1127     }
    1128   }
    1129   delete(center);
    1130   *output << "\t}" << endl;
    1131   *output << ")" << endl;
    1132   *output << "basis<GaussianBasisSet>: (" << endl;
    1133   *output << "\tname = \"3-21G\"" << endl;
    1134   *output << "\tmolecule = $:molecule" << endl;
    1135   *output << ")" << endl;
    1136   output->close();
    1137   delete(output);
    1138   delete(fname);
    1139 
    1140   // second with hessian
    1141   fname = new stringstream;
    1142   *fname << filename << ".hess.in";
    1143   output = new ofstream(fname->str().c_str(), ios::out);
    1144   *output << "% Created by MoleCuilder" << endl;
    1145   *output << "mpqc: (" << endl;
    1146   *output << "\tsavestate = no" << endl;
    1147   *output << "\tdo_gradient = yes" << endl;
    1148   *output << "\tmole<CLHF>: (" << endl;
    1149   *output << "\t\tmaxiter = 200" << endl;
    1150   *output << "\t\tbasis = $:basis" << endl;
    1151   *output << "\t\tmolecule = $:molecule" << endl;
    1152   *output << "\t)" << endl;
    1153   *output << "\tfreq<MolecularFrequencies>: (" << endl;
    1154   *output << "\t\tmolecule=$:molecule" << endl;
    1155   *output << "\t)" << endl;
    1156   *output << ")" << endl;
    1157   *output << "molecule<Molecule>: (" << endl;
    1158   *output << "\tunit = " << (IsAngstroem ? "angstrom" : "bohr" ) << endl;
    1159   *output << "\t{ atoms geometry } = {" << endl;
    1160   center = mol->DetermineCenterOfAll(output);
    1161   // output of atoms
    1162   runner = mol->elemente->start;
    1163   while (runner->next != mol->elemente->end) { // go through every element
    1164     runner = runner->next;
    1165     if (mol->ElementsInMolecule[runner->Z]) { // if this element got atoms
    1166       ElementNo++;
    1167       AtomNo = 0;
    1168       Walker = mol->start;
    1169       while (Walker->next != mol->end) { // go through every atom of this element
    1170         Walker = Walker->next;
    1171         if (Walker->type == runner) { // if this atom fits to element
    1172           AtomNo++;
    1173           *output << "\t\t" << Walker->type->symbol << " [ " << Walker->x.x[0]-center->x[0] << "\t" << Walker->x.x[1]-center->x[1] << "\t" << Walker->x.x[2]-center->x[2] << " ]" << endl;
    1174         }
    1175       }
    1176     }
    1177   }
    1178   delete(center);
    1179   *output << "\t}" << endl;
    1180   *output << ")" << endl;
    1181   *output << "basis<GaussianBasisSet>: (" << endl;
    1182   *output << "\tname = \"3-21G\"" << endl;
    1183   *output << "\tmolecule = $:molecule" << endl;
    1184   *output << ")" << endl;
    1185   output->close();
    1186   delete(output);
    1187   delete(fname);
    1188  
    1189   return true;
     1086        int ElementNo = 0;
     1087        int AtomNo;
     1088        atom *Walker = NULL;
     1089        element *runner = NULL;
     1090        Vector *center = NULL;
     1091        ofstream *output = NULL;
     1092        stringstream *fname = NULL;
     1093       
     1094        // first without hessian
     1095        fname = new stringstream;
     1096        *fname << filename << ".in";
     1097        output = new ofstream(fname->str().c_str(), ios::out);
     1098        *output << "% Created by MoleCuilder" << endl;
     1099        *output << "mpqc: (" << endl;
     1100        *output << "\tsavestate = no" << endl;
     1101        *output << "\tdo_gradient = yes" << endl;
     1102        *output << "\tmole<MBPT2>: (" << endl;
     1103        *output << "\t\tmaxiter = 200" << endl;
     1104        *output << "\t\tbasis = $:basis" << endl;
     1105        *output << "\t\tmolecule = $:molecule" << endl;
     1106        *output << "\t\treference<CLHF>: (" << endl;
     1107        *output << "\t\t\tbasis = $:basis" << endl;
     1108        *output << "\t\t\tmolecule = $:molecule" << endl;
     1109        *output << "\t\t)" << endl;
     1110        *output << "\t)" << endl;
     1111        *output << ")" << endl;
     1112        *output << "molecule<Molecule>: (" << endl;
     1113        *output << "\tunit = " << (IsAngstroem ? "angstrom" : "bohr" ) << endl;
     1114        *output << "\t{ atoms geometry } = {" << endl;
     1115        center = mol->DetermineCenterOfAll(output);
     1116        // output of atoms
     1117        runner = mol->elemente->start;
     1118        while (runner->next != mol->elemente->end) { // go through every element
     1119                runner = runner->next;
     1120                if (mol->ElementsInMolecule[runner->Z]) { // if this element got atoms
     1121                        ElementNo++;
     1122                        AtomNo = 0;
     1123                        Walker = mol->start;
     1124                        while (Walker->next != mol->end) { // go through every atom of this element
     1125                                Walker = Walker->next;
     1126                                if (Walker->type == runner) { // if this atom fits to element
     1127                                        AtomNo++;
     1128                                        *output << "\t\t" << Walker->type->symbol << " [ " << Walker->x.x[0]-center->x[0] << "\t" << Walker->x.x[1]-center->x[1] << "\t" << Walker->x.x[2]-center->x[2] << " ]" << endl;
     1129                                }
     1130                        }
     1131                }
     1132        }
     1133        delete(center);
     1134        *output << "\t}" << endl;
     1135        *output << ")" << endl;
     1136        *output << "basis<GaussianBasisSet>: (" << endl;
     1137        *output << "\tname = \"3-21G\"" << endl;
     1138        *output << "\tmolecule = $:molecule" << endl;
     1139        *output << ")" << endl;
     1140        output->close();
     1141        delete(output);
     1142        delete(fname);
     1143
     1144        // second with hessian
     1145        fname = new stringstream;
     1146        *fname << filename << ".hess.in";
     1147        output = new ofstream(fname->str().c_str(), ios::out);
     1148        *output << "% Created by MoleCuilder" << endl;
     1149        *output << "mpqc: (" << endl;
     1150        *output << "\tsavestate = no" << endl;
     1151        *output << "\tdo_gradient = yes" << endl;
     1152        *output << "\tmole<CLHF>: (" << endl;
     1153        *output << "\t\tmaxiter = 200" << endl;
     1154        *output << "\t\tbasis = $:basis" << endl;
     1155        *output << "\t\tmolecule = $:molecule" << endl;
     1156        *output << "\t)" << endl;
     1157        *output << "\tfreq<MolecularFrequencies>: (" << endl;
     1158        *output << "\t\tmolecule=$:molecule" << endl;
     1159        *output << "\t)" << endl;
     1160        *output << ")" << endl;
     1161        *output << "molecule<Molecule>: (" << endl;
     1162        *output << "\tunit = " << (IsAngstroem ? "angstrom" : "bohr" ) << endl;
     1163        *output << "\t{ atoms geometry } = {" << endl;
     1164        center = mol->DetermineCenterOfAll(output);
     1165        // output of atoms
     1166        runner = mol->elemente->start;
     1167        while (runner->next != mol->elemente->end) { // go through every element
     1168                runner = runner->next;
     1169                if (mol->ElementsInMolecule[runner->Z]) { // if this element got atoms
     1170                        ElementNo++;
     1171                        AtomNo = 0;
     1172                        Walker = mol->start;
     1173                        while (Walker->next != mol->end) { // go through every atom of this element
     1174                                Walker = Walker->next;
     1175                                if (Walker->type == runner) { // if this atom fits to element
     1176                                        AtomNo++;
     1177                                        *output << "\t\t" << Walker->type->symbol << " [ " << Walker->x.x[0]-center->x[0] << "\t" << Walker->x.x[1]-center->x[1] << "\t" << Walker->x.x[2]-center->x[2] << " ]" << endl;
     1178                                }
     1179                        }
     1180                }
     1181        }
     1182        delete(center);
     1183        *output << "\t}" << endl;
     1184        *output << ")" << endl;
     1185        *output << "basis<GaussianBasisSet>: (" << endl;
     1186        *output << "\tname = \"3-21G\"" << endl;
     1187        *output << "\tmolecule = $:molecule" << endl;
     1188        *output << ")" << endl;
     1189        output->close();
     1190        delete(output);
     1191        delete(fname);
     1192       
     1193        return true;
    11901194};
    11911195
     
    11991203 * \param name Name of value in file (at least 3 chars!)
    12001204 * \param sequential 1 - do not reset file pointer to begin of file, 0 - set to beginning
    1201  *        (if file is sequentially parsed this can be way faster! However, beware of multiple values per line, as whole line is read -
    1202  *        best approach: 0 0 0 1 (not resetted only on last value of line) - and of yth, which is now
    1203  *        counted from this unresetted position!)
     1205 *                              (if file is sequentially parsed this can be way faster! However, beware of multiple values per line, as whole line is read -
     1206 *                              best approach: 0 0 0 1 (not resetted only on last value of line) - and of yth, which is now
     1207 *                              counted from this unresetted position!)
    12041208 * \param xth Which among a number of parameters it is (in grid case it's row number as grid is read as a whole!)
    12051209 * \param yth In grid case specifying column number, otherwise the yth \a name matching line
     
    12121216 */
    12131217int config::ParseForParameter(int verbose, ifstream *file, const char *name, int sequential, int const xth, int const yth, int type, void *value, int repetition, int critical) {
    1214   int i,j;  // loop variables
    1215   int length = 0, maxlength = -1;
    1216   long file_position = file->tellg(); // mark current position
    1217   char *dummy1, *dummy, *free_dummy;    // pointers in the line that is read in per step
    1218   dummy1 = free_dummy = (char *) Malloc(256 * sizeof(char), "config::ParseForParameter: *free_dummy");
    1219 
    1220   //fprintf(stderr,"Parsing for %s\n",name); 
    1221   if (repetition == 0)
    1222     //Error(SomeError, "ParseForParameter(): argument repetition must not be 0!");
    1223     return 0;
    1224 
    1225   int line = 0; // marks line where parameter was found
    1226   int found = (type >= grid) ? 0 : (-yth + 1);  // marks if yth parameter name was found
    1227   while((found != repetition)) {
    1228     dummy1 = dummy = free_dummy;
    1229     do {
    1230       file->getline(dummy1, 256); // Read the whole line
    1231       if (file->eof()) {
    1232         if ((critical) && (found == 0)) {
    1233           Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
    1234           //Error(InitReading, name);
    1235           fprintf(stderr,"Error:InitReading, critical %s not found\n", name);
    1236           exit(255);
    1237         } else {
    1238           //if (!sequential)
    1239           file->clear();
    1240           file->seekg(file_position, ios::beg);  // rewind to start position
    1241           Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");         
    1242           return 0;
    1243         }
    1244       }
    1245       line++;
    1246     } while (dummy != NULL && dummy1 != NULL && ((dummy1[0] == '#') || (dummy1[0] == '\0'))); // skip commentary and empty lines
    1247    
    1248     // C++ getline removes newline at end, thus re-add
    1249     if ((dummy1 != NULL) && (strchr(dummy1,'\n') == NULL)) {
    1250       i = strlen(dummy1);
    1251       dummy1[i] = '\n';
    1252       dummy1[i+1] = '\0';
    1253     }
    1254     //fprintf(stderr,"line %i ends at %i, newline at %i\n", line, strlen(dummy1), strchr(dummy1,'\n')-free_dummy);
    1255 
    1256     if (dummy1 == NULL) {
    1257       if (verbose) fprintf(stderr,"Error reading line %i\n",line);
    1258     } else {
    1259       //fprintf(stderr,"Now parsing the line %i: %s\n", line, dummy1);
    1260     }
    1261     // Seek for possible end of keyword on line if given ...
    1262     if (name != NULL) {
    1263       dummy = strchr(dummy1,'\t');  // set dummy on first tab or space which ever's nearer
    1264       if (dummy == NULL) {
    1265         dummy = strchr(dummy1, ' ');  // if not found seek for space
    1266         while ((dummy != NULL) && ((*dummy == '\t') || (*dummy == ' ')))    // skip some more tabs and spaces if necessary
    1267           dummy++;
    1268       }
    1269       if (dummy == NULL) {
    1270         dummy = strchr(dummy1, '\n'); // set on line end then (whole line = keyword)
    1271         //fprintf(stderr,"Error: Cannot find tabs or spaces on line %i in search for %s\n", line, name);
    1272         //Free((void **)&free_dummy);
    1273         //Error(FileOpenParams, NULL);     
    1274       } else {
    1275         //fprintf(stderr,"found tab at %i\n",(char *)dummy-(char *)dummy1);
    1276       }
    1277     } else dummy = dummy1;
    1278     // ... and check if it is the keyword!
    1279     //fprintf(stderr,"name %p, dummy %i/%c, dummy1 %i/%c, strlen(name) %i\n", &name, dummy, *dummy, dummy1, *dummy1, strlen(name));
    1280     if ((name == NULL) || (((dummy-dummy1 >= 3) && (strncmp(dummy1, name, strlen(name)) == 0)) && ((unsigned int)(dummy-dummy1) == strlen(name)))) {
    1281       found++; // found the parameter!
    1282       //fprintf(stderr,"found %s at line %i between %i and %i\n", name, line, dummy1, dummy);   
    1283      
    1284       if (found == repetition) {
    1285         for (i=0;i<xth;i++) { // i = rows
    1286           if (type >= grid) {
    1287             // grid structure means that grid starts on the next line, not right after keyword
    1288             dummy1 = dummy = free_dummy;
    1289             do {
    1290               file->getline(dummy1, 256); // Read the whole line, skip commentary and empty ones
    1291               if (file->eof()) {
    1292                 if ((critical) && (found == 0)) {
    1293                   Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
    1294                   //Error(InitReading, name);
    1295                   fprintf(stderr,"Error:InitReading, critical %s not found\n", name);
    1296                   exit(255);
    1297                 } else {
    1298                   //if (!sequential)
    1299                   file->clear();
    1300                   file->seekg(file_position, ios::beg);  // rewind to start position
    1301                   Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
    1302                   return 0;
    1303                 }
    1304               }
    1305               line++;
    1306             } while ((dummy1[0] == '#') || (dummy1[0] == '\n'));
    1307             if (dummy1 == NULL){
    1308               if (verbose) fprintf(stderr,"Error reading line %i\n", line);
    1309             } else {
    1310               //fprintf(stderr,"Reading next line %i: %s\n", line, dummy1);
    1311             }
    1312           } else { // simple int, strings or doubles start in the same line
    1313             while ((*dummy == '\t') || (*dummy == ' '))  // skip interjacent tabs and spaces
    1314               dummy++;
    1315           }
    1316           // C++ getline removes newline at end, thus re-add
    1317           if ((dummy1 != NULL) && (strchr(dummy1,'\n') == NULL)) {
    1318             j = strlen(dummy1);
    1319             dummy1[j] = '\n';
    1320             dummy1[j+1] = '\0';
    1321           }
    1322  
    1323           int start = (type >= grid) ? 0 : yth-1 ;
    1324           for (j=start;j<yth;j++) { // j = columns
    1325             // check for lower triangular area and upper triangular area
    1326             if ( ((i > j) && (type == upper_trigrid)) || ((j > i) && (type == lower_trigrid))) {
    1327               *((double *)value) = 0.0;
    1328               fprintf(stderr,"%f\t",*((double *)value));
    1329               value = (void *)((long)value + sizeof(double));
    1330               //value += sizeof(double);
    1331             } else {
    1332               // otherwise we must skip all interjacent tabs and spaces and find next value
    1333               dummy1 = dummy;
    1334               dummy = strchr(dummy1, '\t'); // seek for tab or space
    1335               if (dummy == NULL)
    1336                 dummy = strchr(dummy1, ' ');  // if not found seek for space
    1337               if (dummy == NULL) { // if still zero returned ...
    1338                 dummy = strchr(dummy1, '\n');  // ... at line end then
    1339                 if ((j < yth-1) && (type < 4)) {  // check if xth value or not yet
    1340                   if (critical) {
    1341                     if (verbose) fprintf(stderr,"Error: EoL at %i and still missing %i value(s) for parameter %s\n", line, yth-j, name);
    1342                     Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
    1343                     //return 0;
    1344                     exit(255);
    1345                     //Error(FileOpenParams, NULL);     
    1346                   } else {
    1347                     //if (!sequential)
    1348                     file->clear();
    1349                     file->seekg(file_position, ios::beg);  // rewind to start position
    1350                     Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
    1351                     return 0;
    1352                   }
    1353                 }
    1354               } else {
    1355                 //fprintf(stderr,"found tab at %i\n",(char *)dummy-(char *)free_dummy);
    1356               }
    1357               if (*dummy1 == '#') {
    1358                 // found comment, skipping rest of line
    1359                 //if (verbose) fprintf(stderr,"Error: '#' at %i and still missing %i value(s) for parameter %s\n", line, yth-j, name);
    1360                 if (!sequential) { // here we need it!
    1361                   file->seekg(file_position, ios::beg);  // rewind to start position
    1362                 }
    1363                 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
    1364                 return 0;
    1365               }
    1366               //fprintf(stderr,"value from %i to %i\n",(char *)dummy1-(char *)free_dummy,(char *)dummy-(char *)free_dummy);
    1367               switch(type) {
    1368                 case (row_int):
    1369                   *((int *)value) = atoi(dummy1);
    1370                   if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name);
    1371                   if (verbose) fprintf(stderr,"%i\t",*((int *)value));
    1372                     value = (void *)((long)value + sizeof(int));
    1373                     //value += sizeof(int);
    1374                   break;
    1375                 case(row_double):
    1376                 case(grid):
    1377                 case(lower_trigrid):
    1378                 case(upper_trigrid):
    1379                   *((double *)value) = atof(dummy1);
    1380                   if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name);
    1381                   if (verbose) fprintf(stderr,"%lg\t",*((double *)value));
    1382                   value = (void *)((long)value + sizeof(double));
    1383                   //value += sizeof(double);
    1384                   break;
    1385                 case(double_type):
    1386                   *((double *)value) = atof(dummy1);
    1387                   if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %lg\n", name, *((double *) value));
    1388                   //value += sizeof(double);
    1389                   break;
    1390                 case(int_type):
    1391                   *((int *)value) = atoi(dummy1);
    1392                   if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %i\n", name, *((int *) value));
    1393                   //value += sizeof(int);
    1394                   break;
    1395                 default:
    1396                 case(string_type):
    1397                   if (value != NULL) {
    1398                     //if (maxlength == -1) maxlength = strlen((char *)value); // get maximum size of string array
    1399                     maxlength = MAXSTRINGSIZE;
    1400                     length = maxlength > (dummy-dummy1) ? (dummy-dummy1) : maxlength; // cap at maximum
    1401                     strncpy((char *)value, dummy1, length);  // copy as much
    1402                     ((char *)value)[length] = '\0';  // and set end marker
    1403                     if ((verbose) && (i == xth-1)) fprintf(stderr,"%s is '%s' (%i chars)\n",name,((char *) value), length);
    1404                     //value += sizeof(char);
    1405                   } else {
    1406                   }
    1407                 break;
    1408               }
    1409             }
    1410             while (*dummy == '\t')
    1411               dummy++;
    1412           }
    1413         }
    1414       }
    1415     }
    1416   }
    1417   if ((type >= row_int) && (verbose)) fprintf(stderr,"\n");
    1418   Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
    1419   if (!sequential) {
    1420     file->clear();
    1421     file->seekg(file_position, ios::beg);  // rewind to start position
    1422   }
    1423   //fprintf(stderr, "End of Parsing\n\n");
    1424  
    1425   return (found); // true if found, false if not
     1218        int i,j;        // loop variables
     1219        int length = 0, maxlength = -1;
     1220        long file_position = file->tellg(); // mark current position
     1221        char *dummy1, *dummy, *free_dummy;              // pointers in the line that is read in per step
     1222        dummy1 = free_dummy = (char *) Malloc(256 * sizeof(char), "config::ParseForParameter: *free_dummy");
     1223
     1224        //fprintf(stderr,"Parsing for %s\n",name);     
     1225        if (repetition == 0)
     1226                //Error(SomeError, "ParseForParameter(): argument repetition must not be 0!");
     1227                return 0;
     1228
     1229        int line = 0; // marks line where parameter was found
     1230        int found = (type >= grid) ? 0 : (-yth + 1);    // marks if yth parameter name was found
     1231        while((found != repetition)) {
     1232                dummy1 = dummy = free_dummy;
     1233                do {
     1234                        file->getline(dummy1, 256); // Read the whole line
     1235                        if (file->eof()) {
     1236                                if ((critical) && (found == 0)) {
     1237                                        Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
     1238                                        //Error(InitReading, name);
     1239                                        fprintf(stderr,"Error:InitReading, critical %s not found\n", name);
     1240                                        exit(255);
     1241                                } else {
     1242                                        //if (!sequential)
     1243                                        file->clear();
     1244                                        file->seekg(file_position, ios::beg);   // rewind to start position
     1245                                        Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");                                   
     1246                                        return 0;
     1247                                }
     1248                        }
     1249                        line++;
     1250                } while (dummy != NULL && dummy1 != NULL && ((dummy1[0] == '#') || (dummy1[0] == '\0'))); // skip commentary and empty lines
     1251               
     1252                // C++ getline removes newline at end, thus re-add
     1253                if ((dummy1 != NULL) && (strchr(dummy1,'\n') == NULL)) {
     1254                        i = strlen(dummy1);
     1255                        dummy1[i] = '\n';
     1256                        dummy1[i+1] = '\0';
     1257                }
     1258                //fprintf(stderr,"line %i ends at %i, newline at %i\n", line, strlen(dummy1), strchr(dummy1,'\n')-free_dummy);
     1259
     1260                if (dummy1 == NULL) {
     1261                        if (verbose) fprintf(stderr,"Error reading line %i\n",line);
     1262                } else {
     1263                        //fprintf(stderr,"Now parsing the line %i: %s\n", line, dummy1);
     1264                }
     1265                // Seek for possible end of keyword on line if given ...
     1266                if (name != NULL) {
     1267                        dummy = strchr(dummy1,'\t');    // set dummy on first tab or space which ever's nearer
     1268                        if (dummy == NULL) {
     1269                                dummy = strchr(dummy1, ' ');    // if not found seek for space
     1270                                while ((dummy != NULL) && ((*dummy == '\t') || (*dummy == ' ')))                // skip some more tabs and spaces if necessary
     1271                                        dummy++;
     1272                        }
     1273                        if (dummy == NULL) {
     1274                                dummy = strchr(dummy1, '\n'); // set on line end then (whole line = keyword)
     1275                                //fprintf(stderr,"Error: Cannot find tabs or spaces on line %i in search for %s\n", line, name);
     1276                                //Free((void **)&free_dummy);
     1277                                //Error(FileOpenParams, NULL);                 
     1278                        } else {
     1279                                //fprintf(stderr,"found tab at %i\n",(char *)dummy-(char *)dummy1);
     1280                        }
     1281                } else dummy = dummy1;
     1282                // ... and check if it is the keyword!
     1283                //fprintf(stderr,"name %p, dummy %i/%c, dummy1 %i/%c, strlen(name) %i\n", &name, dummy, *dummy, dummy1, *dummy1, strlen(name));
     1284                if ((name == NULL) || (((dummy-dummy1 >= 3) && (strncmp(dummy1, name, strlen(name)) == 0)) && ((unsigned int)(dummy-dummy1) == strlen(name)))) {
     1285                        found++; // found the parameter!
     1286                        //fprintf(stderr,"found %s at line %i between %i and %i\n", name, line, dummy1, dummy);         
     1287                       
     1288                        if (found == repetition) {
     1289                                for (i=0;i<xth;i++) { // i = rows
     1290                                        if (type >= grid) {
     1291                                                // grid structure means that grid starts on the next line, not right after keyword
     1292                                                dummy1 = dummy = free_dummy;
     1293                                                do {
     1294                                                        file->getline(dummy1, 256); // Read the whole line, skip commentary and empty ones
     1295                                                        if (file->eof()) {
     1296                                                                if ((critical) && (found == 0)) {
     1297                                                                        Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
     1298                                                                        //Error(InitReading, name);
     1299                                                                        fprintf(stderr,"Error:InitReading, critical %s not found\n", name);
     1300                                                                        exit(255);
     1301                                                                } else {
     1302                                                                        //if (!sequential)
     1303                                                                        file->clear();
     1304                                                                        file->seekg(file_position, ios::beg);   // rewind to start position
     1305                                                                        Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
     1306                                                                        return 0;
     1307                                                                }
     1308                                                        }
     1309                                                        line++;
     1310                                                } while ((dummy1[0] == '#') || (dummy1[0] == '\n'));
     1311                                                if (dummy1 == NULL){
     1312                                                        if (verbose) fprintf(stderr,"Error reading line %i\n", line);
     1313                                                } else {
     1314                                                        //fprintf(stderr,"Reading next line %i: %s\n", line, dummy1);
     1315                                                }
     1316                                        } else { // simple int, strings or doubles start in the same line
     1317                                                while ((*dummy == '\t') || (*dummy == ' '))      // skip interjacent tabs and spaces
     1318                                                        dummy++;
     1319                                        }
     1320                                        // C++ getline removes newline at end, thus re-add
     1321                                        if ((dummy1 != NULL) && (strchr(dummy1,'\n') == NULL)) {
     1322                                                j = strlen(dummy1);
     1323                                                dummy1[j] = '\n';
     1324                                                dummy1[j+1] = '\0';
     1325                                        }
     1326       
     1327                                        int start = (type >= grid) ? 0 : yth-1 ;
     1328                                        for (j=start;j<yth;j++) { // j = columns
     1329                                                // check for lower triangular area and upper triangular area
     1330                                                if ( ((i > j) && (type == upper_trigrid)) || ((j > i) && (type == lower_trigrid))) {
     1331                                                        *((double *)value) = 0.0;
     1332                                                        fprintf(stderr,"%f\t",*((double *)value));
     1333                                                        value = (void *)((long)value + sizeof(double));
     1334                                                        //value += sizeof(double);
     1335                                                } else {
     1336                                                        // otherwise we must skip all interjacent tabs and spaces and find next value
     1337                                                        dummy1 = dummy;
     1338                                                        dummy = strchr(dummy1, '\t'); // seek for tab or space
     1339                                                        if (dummy == NULL)
     1340                                                                dummy = strchr(dummy1, ' ');    // if not found seek for space
     1341                                                        if (dummy == NULL) { // if still zero returned ...
     1342                                                                dummy = strchr(dummy1, '\n');   // ... at line end then
     1343                                                                if ((j < yth-1) && (type < 4)) {        // check if xth value or not yet
     1344                                                                        if (critical) {
     1345                                                                                if (verbose) fprintf(stderr,"Error: EoL at %i and still missing %i value(s) for parameter %s\n", line, yth-j, name);
     1346                                                                                Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
     1347                                                                                //return 0;
     1348                                                                                exit(255);
     1349                                                                                //Error(FileOpenParams, NULL);                 
     1350                                                                        } else {
     1351                                                                                //if (!sequential)
     1352                                                                                file->clear();
     1353                                                                                file->seekg(file_position, ios::beg);   // rewind to start position
     1354                                                                                Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
     1355                                                                                return 0;
     1356                                                                        }
     1357                                                                }
     1358                                                        } else {
     1359                                                                //fprintf(stderr,"found tab at %i\n",(char *)dummy-(char *)free_dummy);
     1360                                                        }
     1361                                                        if (*dummy1 == '#') {
     1362                                                                // found comment, skipping rest of line
     1363                                                                //if (verbose) fprintf(stderr,"Error: '#' at %i and still missing %i value(s) for parameter %s\n", line, yth-j, name);
     1364                                                                if (!sequential) { // here we need it!
     1365                                                                        file->seekg(file_position, ios::beg);   // rewind to start position
     1366                                                                }
     1367                                                                Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
     1368                                                                return 0;
     1369                                                        }
     1370                                                        //fprintf(stderr,"value from %i to %i\n",(char *)dummy1-(char *)free_dummy,(char *)dummy-(char *)free_dummy);
     1371                                                        switch(type) {
     1372                                                                case (row_int):
     1373                                                                        *((int *)value) = atoi(dummy1);
     1374                                                                        if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name);
     1375                                                                        if (verbose) fprintf(stderr,"%i\t",*((int *)value));
     1376                                                                                value = (void *)((long)value + sizeof(int));
     1377                                                                                //value += sizeof(int);
     1378                                                                        break;
     1379                                                                case(row_double):
     1380                                                                case(grid):
     1381                                                                case(lower_trigrid):
     1382                                                                case(upper_trigrid):
     1383                                                                        *((double *)value) = atof(dummy1);
     1384                                                                        if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name);
     1385                                                                        if (verbose) fprintf(stderr,"%lg\t",*((double *)value));
     1386                                                                        value = (void *)((long)value + sizeof(double));
     1387                                                                        //value += sizeof(double);
     1388                                                                        break;
     1389                                                                case(double_type):
     1390                                                                        *((double *)value) = atof(dummy1);
     1391                                                                        if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %lg\n", name, *((double *) value));
     1392                                                                        //value += sizeof(double);
     1393                                                                        break;
     1394                                                                case(int_type):
     1395                                                                        *((int *)value) = atoi(dummy1);
     1396                                                                        if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %i\n", name, *((int *) value));
     1397                                                                        //value += sizeof(int);
     1398                                                                        break;
     1399                                                                default:
     1400                                                                case(string_type):
     1401                                                                        if (value != NULL) {
     1402                                                                                //if (maxlength == -1) maxlength = strlen((char *)value); // get maximum size of string array
     1403                                                                                maxlength = MAXSTRINGSIZE;
     1404                                                                                length = maxlength > (dummy-dummy1) ? (dummy-dummy1) : maxlength; // cap at maximum
     1405                                                                                strncpy((char *)value, dummy1, length); // copy as much
     1406                                                                                ((char *)value)[length] = '\0'; // and set end marker
     1407                                                                                if ((verbose) && (i == xth-1)) fprintf(stderr,"%s is '%s' (%i chars)\n",name,((char *) value), length);
     1408                                                                                //value += sizeof(char);
     1409                                                                        } else {
     1410                                                                        }
     1411                                                                break;
     1412                                                        }
     1413                                                }
     1414                                                while (*dummy == '\t')
     1415                                                        dummy++;
     1416                                        }
     1417                                }
     1418                        }
     1419                }
     1420        }
     1421        if ((type >= row_int) && (verbose)) fprintf(stderr,"\n");
     1422        Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
     1423        if (!sequential) {
     1424                file->clear();
     1425                file->seekg(file_position, ios::beg);   // rewind to start position
     1426        }
     1427        //fprintf(stderr, "End of Parsing\n\n");
     1428       
     1429        return (found); // true if found, false if not
    14261430}
  • src/datacreator.cpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    11/** \file datacreator.cpp
    22 *
    3  * Declarations of assisting functions in creating data and plot files. 
    4  *   
     3 * Declarations of assisting functions in creating data and plot files.
     4 *
    55 */
    66
     
    1919bool OpenOutputFile(ofstream &output, const char *dir, const char *filename)
    2020{
    21   stringstream name;
    22   name << dir << "/" << filename;
    23   output.open(name.str().c_str(), ios::out);
    24   if (output == NULL) {
    25     cout << "Unable to open " << name.str() << " for writing, is directory correct?" << endl;
    26     return false;
    27   }
    28   return true;
    29 }; 
     21        stringstream name;
     22        name << dir << "/" << filename;
     23        output.open(name.str().c_str(), ios::out);
     24        if (output == NULL) {
     25                cout << "Unable to open " << name.str() << " for writing, is directory correct?" << endl;
     26                return false;
     27        }
     28        return true;
     29};
    3030
    3131/** Opens a file for appending with \a *filename in \a *dir.
     
    3737bool AppendOutputFile(ofstream &output, const char *dir, const char *filename)
    3838{
    39   stringstream name;
    40   name << dir << "/" << filename;
    41   output.open(name.str().c_str(), ios::app);
    42   if (output == NULL) {
    43     cout << "Unable to open " << name.str() << " for writing, is directory correct?" << endl;
    44     return false;
    45   }
    46   return true;
    47 }; 
     39        stringstream name;
     40        name << dir << "/" << filename;
     41        output.open(name.str().c_str(), ios::app);
     42        if (output == NULL) {
     43                cout << "Unable to open " << name.str() << " for writing, is directory correct?" << endl;
     44                return false;
     45        }
     46        return true;
     47};
    4848
    4949/** Plots an energy vs. order.
     
    5454 * \return true if file was written successfully
    5555 */
    56 bool CreateDataEnergyOrder(class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 
    57 {
    58   stringstream filename;
    59   ofstream output;
    60 
    61   filename << prefix << ".dat";
    62   if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
    63   cout << msg << endl;
    64   output << "# " << msg << ", created on " << datum;
    65   output << "#Order\tFrag.No.\t" << Fragments.Header << endl;
    66   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
    67     for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) {
    68       for(int j=Fragments.RowCounter[ KeySet.OrderSet[BondOrder][i] ];j--;)
    69         for(int k=Fragments.ColumnCounter;k--;)
    70           Fragments.Matrix[Fragments.MatrixCounter][j][k] += Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
    71     }
    72     output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder];
    73     for (int l=0;l<Fragments.ColumnCounter;l++)
    74       output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l];
    75     output << endl;
    76   }
    77   output.close();
    78   return true;
     56bool CreateDataEnergyOrder(class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum)
     57{
     58        stringstream filename;
     59        ofstream output;
     60
     61        filename << prefix << ".dat";
     62        if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
     63        cout << msg << endl;
     64        output << "# " << msg << ", created on " << datum;
     65        output << "#Order\tFrag.No.\t" << Fragments.Header << endl;
     66        for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     67                for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) {
     68                        for(int j=Fragments.RowCounter[ KeySet.OrderSet[BondOrder][i] ];j--;)
     69                                for(int k=Fragments.ColumnCounter;k--;)
     70                                        Fragments.Matrix[Fragments.MatrixCounter][j][k] += Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
     71                }
     72                output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder];
     73                for (int l=0;l<Fragments.ColumnCounter;l++)
     74                        output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l];
     75                output << endl;
     76        }
     77        output.close();
     78        return true;
    7979};
    8080
     
    8787 * \return true if file was written successfully
    8888 */
    89 bool CreateDataDeltaEnergyOrder(class EnergyMatrix &Energy, class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 
    90 {
    91   stringstream filename;
    92   ofstream output;
    93 
    94   filename << prefix << ".dat";
    95   if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
    96   cout << msg << endl;
    97   output << "# " << msg << ", created on " << datum;
    98   output << "#Order\tFrag.No.\t" << Fragments.Header << endl;
    99   Fragments.SetLastMatrix(Energy.Matrix[Energy.MatrixCounter],0);
    100   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
    101     for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) {
    102       for(int j=Fragments.RowCounter[ KeySet.OrderSet[BondOrder][i] ];j--;)
    103         for(int k=Fragments.ColumnCounter;k--;)
    104           Fragments.Matrix[Fragments.MatrixCounter][j][k] -= Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
    105     }
    106     output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder];
    107     for (int l=0;l<Fragments.ColumnCounter;l++)
    108       if (fabs(Energy.Matrix[Energy.MatrixCounter][ Energy.RowCounter[Energy.MatrixCounter]-1 ][l]) < MYEPSILON)
    109         output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l];
    110       else
    111         output << scientific << "\t" << (Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l] / Energy.Matrix[Energy.MatrixCounter][ Energy.RowCounter[Energy.MatrixCounter]-1 ][l]);
    112     output << endl;
    113   }
    114   output.close();
    115   return true;
     89bool CreateDataDeltaEnergyOrder(class EnergyMatrix &Energy, class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum)
     90{
     91        stringstream filename;
     92        ofstream output;
     93
     94        filename << prefix << ".dat";
     95        if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
     96        cout << msg << endl;
     97        output << "# " << msg << ", created on " << datum;
     98        output << "#Order\tFrag.No.\t" << Fragments.Header << endl;
     99        Fragments.SetLastMatrix(Energy.Matrix[Energy.MatrixCounter],0);
     100        for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     101                for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) {
     102                        for(int j=Fragments.RowCounter[ KeySet.OrderSet[BondOrder][i] ];j--;)
     103                                for(int k=Fragments.ColumnCounter;k--;)
     104                                        Fragments.Matrix[Fragments.MatrixCounter][j][k] -= Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
     105                }
     106                output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder];
     107                for (int l=0;l<Fragments.ColumnCounter;l++)
     108                        if (fabs(Energy.Matrix[Energy.MatrixCounter][ Energy.RowCounter[Energy.MatrixCounter]-1 ][l]) < MYEPSILON)
     109                                output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l];
     110                        else
     111                                output << scientific << "\t" << (Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l] / Energy.Matrix[Energy.MatrixCounter][ Energy.RowCounter[Energy.MatrixCounter]-1 ][l]);
     112                output << endl;
     113        }
     114        output.close();
     115        return true;
    116116};
    117117
     
    126126bool CreateDataForcesOrder(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateForce)(class MatrixContainer &, int))
    127127{
    128   stringstream filename;
    129   ofstream output;
    130 
    131   filename << prefix << ".dat";
    132   if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
    133   cout << msg << endl;
    134   output << "# " << msg << ", created on " << datum;
    135   output << "# Order\tFrag.No.\t" << Fragments.Header << endl;
    136   Fragments.SetLastMatrix(0.,0);
    137   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
    138     Fragments.SumSubForces(Fragments, KeySet, BondOrder, 1.);
    139     output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder];
    140     CreateForce(Fragments, Fragments.MatrixCounter);
    141     for (int l=0;l<Fragments.ColumnCounter;l++)
    142       output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter] ][l];
    143     output << endl;
    144   }
    145   output.close();
    146   return true;
     128        stringstream filename;
     129        ofstream output;
     130
     131        filename << prefix << ".dat";
     132        if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
     133        cout << msg << endl;
     134        output << "# " << msg << ", created on " << datum;
     135        output << "# Order\tFrag.No.\t" << Fragments.Header << endl;
     136        Fragments.SetLastMatrix(0.,0);
     137        for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     138                Fragments.SumSubForces(Fragments, KeySet, BondOrder, 1.);
     139                output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder];
     140                CreateForce(Fragments, Fragments.MatrixCounter);
     141                for (int l=0;l<Fragments.ColumnCounter;l++)
     142                        output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter] ][l];
     143                output << endl;
     144        }
     145        output.close();
     146        return true;
    147147};
    148148
     
    158158bool CreateDataDeltaForcesOrder(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateForce)(class MatrixContainer &, int))
    159159{
    160   stringstream filename;
    161   ofstream output;
    162 
    163   filename << prefix << ".dat";
    164   if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
    165   cout << msg << endl;
    166   output << "# " << msg << ", created on " << datum;
    167   output << "# Order\tFrag.No.\t" << Fragments.Header << endl;
    168   Fragments.SetLastMatrix(Force.Matrix[Force.MatrixCounter],0);
    169   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
    170     Fragments.SumSubForces(Fragments, KeySet, BondOrder, -1.);
    171     output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder];
    172     CreateForce(Fragments, Fragments.MatrixCounter);
    173     for (int l=0;l<Fragments.ColumnCounter;l++)
    174       output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter] ][l];
    175     output << endl;
    176   }
    177   output.close();
    178   return true;
     160        stringstream filename;
     161        ofstream output;
     162
     163        filename << prefix << ".dat";
     164        if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
     165        cout << msg << endl;
     166        output << "# " << msg << ", created on " << datum;
     167        output << "# Order\tFrag.No.\t" << Fragments.Header << endl;
     168        Fragments.SetLastMatrix(Force.Matrix[Force.MatrixCounter],0);
     169        for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     170                Fragments.SumSubForces(Fragments, KeySet, BondOrder, -1.);
     171                output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder];
     172                CreateForce(Fragments, Fragments.MatrixCounter);
     173                for (int l=0;l<Fragments.ColumnCounter;l++)
     174                        output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter] ][l];
     175                output << endl;
     176        }
     177        output.close();
     178        return true;
    179179};
    180180
     
    188188 * \return true if file was written successfully
    189189 */
    190 bool CreateDataDeltaForcesOrderPerAtom(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 
    191 {
    192   stringstream filename;
    193   ofstream output;
    194   double norm = 0.;
    195 
    196   filename << prefix << ".dat";
    197   if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
    198   cout << msg << endl;
    199   output << "# " << msg << ", created on " << datum;
    200   output << "# AtomNo\t" << Fragments.Header << endl;
    201   Fragments.SetLastMatrix(Force.Matrix[Force.MatrixCounter], 0);
    202   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
    203     //cout << "Current order is " << BondOrder << "." << endl;
    204     Fragments.SumSubForces(Fragments, KeySet, BondOrder, -1.);
    205     // errors per atom
    206     output << endl << "#Order\t" << BondOrder+1 << endl;
    207     for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) {
    208       output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t";
    209       for (int l=0;l<Fragments.ColumnCounter;l++) {
    210         if (((l+1) % 3) == 0) {
    211           norm = 0.;
    212           for (int m=0;m<NDIM;m++)
    213             norm += Force.Matrix[Force.MatrixCounter][ j ][l+m]*Force.Matrix[Force.MatrixCounter][ j ][l+m];
    214           norm = sqrt(norm);
    215         }                                                                                                           
    216 //        if (norm < MYEPSILON)
    217           output << scientific << Fragments.Matrix[Fragments.MatrixCounter][ j ][l] << "\t";
    218 //        else
    219 //          output << scientific << (Fragments.Matrix[Fragments.MatrixCounter][ j ][l] / norm) << "\t";
    220       }
    221       output << endl;
    222     }
    223     output << endl;
    224   }
    225   output.close();
    226   return true;
     190bool CreateDataDeltaForcesOrderPerAtom(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum)
     191{
     192        stringstream filename;
     193        ofstream output;
     194        double norm = 0.;
     195
     196        filename << prefix << ".dat";
     197        if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
     198        cout << msg << endl;
     199        output << "# " << msg << ", created on " << datum;
     200        output << "# AtomNo\t" << Fragments.Header << endl;
     201        Fragments.SetLastMatrix(Force.Matrix[Force.MatrixCounter], 0);
     202        for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     203                //cout << "Current order is " << BondOrder << "." << endl;
     204                Fragments.SumSubForces(Fragments, KeySet, BondOrder, -1.);
     205                // errors per atom
     206                output << endl << "#Order\t" << BondOrder+1 << endl;
     207                for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) {
     208                        output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t";
     209                        for (int l=0;l<Fragments.ColumnCounter;l++) {
     210                                if (((l+1) % 3) == 0) {
     211                                        norm = 0.;
     212                                        for (int m=0;m<NDIM;m++)
     213                                                norm += Force.Matrix[Force.MatrixCounter][ j ][l+m]*Force.Matrix[Force.MatrixCounter][ j ][l+m];
     214                                        norm = sqrt(norm);
     215                                }                                                                                                                                                                                                                                                                                                                                                                                                               
     216//                              if (norm < MYEPSILON)
     217                                        output << scientific << Fragments.Matrix[Fragments.MatrixCounter][ j ][l] << "\t";
     218//                              else
     219//                                      output << scientific << (Fragments.Matrix[Fragments.MatrixCounter][ j ][l] / norm) << "\t";
     220                        }
     221                        output << endl;
     222                }
     223                output << endl;
     224        }
     225        output.close();
     226        return true;
    227227};
    228228
     
    235235 * \return true if file was written successfully
    236236 */
    237 bool CreateDataForcesOrderPerAtom(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 
    238 {
    239   stringstream filename;
    240   ofstream output;
    241 
    242   filename << prefix << ".dat";
    243   if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
    244   cout << msg << endl;
    245   output << "# " << msg << ", created on " << datum;
    246   output << "# AtomNo\t" << Fragments.Header << endl;
    247   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
    248     //cout << "Current order is " << BondOrder << "." << endl;
    249     Fragments.SumSubForces(Fragments, KeySet, BondOrder, 1.);
    250     // errors per atom
    251     output << endl << "#Order\t" << BondOrder+1 << endl;
    252     for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) {
    253       output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t";
    254       for (int l=0;l<Fragments.ColumnCounter;l++)
    255         output << scientific << Fragments.Matrix[Fragments.MatrixCounter][ j ][l] << "\t";
    256       output << endl;
    257     }
    258     output << endl;
    259   }
    260   output.close();
    261   return true;
     237bool CreateDataForcesOrderPerAtom(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum)
     238{
     239        stringstream filename;
     240        ofstream output;
     241
     242        filename << prefix << ".dat";
     243        if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
     244        cout << msg << endl;
     245        output << "# " << msg << ", created on " << datum;
     246        output << "# AtomNo\t" << Fragments.Header << endl;
     247        for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     248                //cout << "Current order is " << BondOrder << "." << endl;
     249                Fragments.SumSubForces(Fragments, KeySet, BondOrder, 1.);
     250                // errors per atom
     251                output << endl << "#Order\t" << BondOrder+1 << endl;
     252                for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) {
     253                        output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t";
     254                        for (int l=0;l<Fragments.ColumnCounter;l++)
     255                                output << scientific << Fragments.Matrix[Fragments.MatrixCounter][ j ][l] << "\t";
     256                        output << endl;
     257                }
     258                output << endl;
     259        }
     260        output.close();
     261        return true;
    262262};
    263263
     
    266266bool CreateDataFragment(class MatrixContainer &Fragment, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateFragment)(class MatrixContainer &, int))
    267267{
    268   stringstream filename;
    269   ofstream output;
    270 
    271   filename << prefix << ".dat";
    272   if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
    273   cout << msg << endl;
    274   output << "# " << msg << ", created on " << datum << endl;
    275   output << "#Order\tFrag.No.\t" << Fragment.Header << endl;
    276   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
    277     for(int i=0;i<KeySet.FragmentsPerOrder[BondOrder];i++) {
    278       output << BondOrder+1 << "\t" << KeySet.OrderSet[BondOrder][i]+1;
    279       CreateFragment(Fragment, KeySet.OrderSet[BondOrder][i]);
    280       for (int l=0;l<Fragment.ColumnCounter;l++)
    281         output << scientific << "\t" << Fragment.Matrix[ KeySet.OrderSet[BondOrder][i] ][ Fragment.RowCounter[ KeySet.OrderSet[BondOrder][i] ] ][l];
    282       output << endl;
    283     }
    284   }
    285   output.close();
    286   return true;
     268        stringstream filename;
     269        ofstream output;
     270
     271        filename << prefix << ".dat";
     272        if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
     273        cout << msg << endl;
     274        output << "# " << msg << ", created on " << datum << endl;
     275        output << "#Order\tFrag.No.\t" << Fragment.Header << endl;
     276        for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     277                for(int i=0;i<KeySet.FragmentsPerOrder[BondOrder];i++) {
     278                        output << BondOrder+1 << "\t" << KeySet.OrderSet[BondOrder][i]+1;
     279                        CreateFragment(Fragment, KeySet.OrderSet[BondOrder][i]);
     280                        for (int l=0;l<Fragment.ColumnCounter;l++)
     281                                output << scientific << "\t" << Fragment.Matrix[ KeySet.OrderSet[BondOrder][i] ][ Fragment.RowCounter[ KeySet.OrderSet[BondOrder][i] ] ][l];
     282                        output << endl;
     283                }
     284        }
     285        output.close();
     286        return true;
    287287};
    288288
     
    291291 * \param &KeySet KeySetsContainer with associations of each fragment to a bond order
    292292 * \param BondOrder current bond order
    293  */ 
     293 */
    294294void CreateMaxFragmentOrder(class MatrixContainer &Fragments, class KeySetsContainer &KeySet, int BondOrder)
    295295{
    296   for(int j=Fragments.RowCounter[ Fragments.MatrixCounter ];j--;) {
    297     for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) {
    298       if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) < fabs(Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][1])) {
    299         for (int k=Fragments.ColumnCounter;k--;)
    300           Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
    301       }
    302     }     
    303   }
     296        for(int j=Fragments.RowCounter[ Fragments.MatrixCounter ];j--;) {
     297                for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) {
     298                        if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) < fabs(Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][1])) {
     299                                for (int k=Fragments.ColumnCounter;k--;)
     300                                        Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
     301                        }
     302                }
     303        }
    304304};
    305305
     
    308308 * \param &KeySet KeySetsContainer with associations of each fragment to a bond order
    309309 * \param BondOrder current bond order
    310  */ 
     310 */
    311311void CreateMinFragmentOrder(class MatrixContainer &Fragments, class KeySetsContainer &KeySet, int BondOrder)
    312312{
    313   for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) {
    314     int i=0;
    315     do {  // first get a minimum value unequal to 0
    316       for (int k=Fragments.ColumnCounter;k--;)
    317         Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
    318       i++;
    319     } while ((fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) < MYEPSILON) && (i<KeySet.FragmentsPerOrder[BondOrder]));
    320     for(;i<KeySet.FragmentsPerOrder[BondOrder];i++) { // then find lowest
    321       if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) > fabs(Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][1])) {
    322         for (int k=Fragments.ColumnCounter;k--;)
    323           Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
    324       }
    325     }     
    326   }
     313        for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) {
     314                int i=0;
     315                do {    // first get a minimum value unequal to 0
     316                        for (int k=Fragments.ColumnCounter;k--;)
     317                                Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
     318                        i++;
     319                } while ((fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) < MYEPSILON) && (i<KeySet.FragmentsPerOrder[BondOrder]));
     320                for(;i<KeySet.FragmentsPerOrder[BondOrder];i++) { // then find lowest
     321                        if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) > fabs(Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][1])) {
     322                                for (int k=Fragments.ColumnCounter;k--;)
     323                                        Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
     324                        }
     325                }
     326        }
    327327};
    328328
     
    331331bool CreateDataFragmentOrder(class MatrixContainer &Fragment, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateFragmentOrder)(class MatrixContainer &, class KeySetsContainer &, int))
    332332{
    333   stringstream filename;
    334   ofstream output;
    335 
    336   filename << prefix << ".dat";
    337   if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
    338   cout << msg << endl;
    339   output << "# " << msg << ", created on " << datum;
    340   output << "#Order\tFrag.No.\t" << Fragment.Header << endl;
    341   // max
    342   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
    343     Fragment.SetLastMatrix(0.,0);
    344     CreateFragmentOrder(Fragment, KeySet, BondOrder);
    345     output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder];
    346     for (int l=0;l<Fragment.ColumnCounter;l++)
    347       output << scientific << "\t" << Fragment.Matrix[ Fragment.MatrixCounter ][ Fragment.RowCounter[ Fragment.MatrixCounter ]-1 ][l];
    348     output << endl;
    349   }
    350   output.close();
    351   return true;
     333        stringstream filename;
     334        ofstream output;
     335
     336        filename << prefix << ".dat";
     337        if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
     338        cout << msg << endl;
     339        output << "# " << msg << ", created on " << datum;
     340        output << "#Order\tFrag.No.\t" << Fragment.Header << endl;
     341        // max
     342        for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     343                Fragment.SetLastMatrix(0.,0);
     344                CreateFragmentOrder(Fragment, KeySet, BondOrder);
     345                output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder];
     346                for (int l=0;l<Fragment.ColumnCounter;l++)
     347                        output << scientific << "\t" << Fragment.Matrix[ Fragment.MatrixCounter ][ Fragment.RowCounter[ Fragment.MatrixCounter ]-1 ][l];
     348                output << endl;
     349        }
     350        output.close();
     351        return true;
    352352};
    353353
     
    358358void CreateEnergy(class MatrixContainer &Energy, int MatrixNumber)
    359359{
    360   for(int k=0;k<Energy.ColumnCounter;k++)
    361     Energy.Matrix[MatrixNumber][ Energy.RowCounter[MatrixNumber] ] [k] =  Energy.Matrix[MatrixNumber][ Energy.RowCounter[MatrixNumber]-1 ] [k];
     360        for(int k=0;k<Energy.ColumnCounter;k++)
     361                Energy.Matrix[MatrixNumber][ Energy.RowCounter[MatrixNumber] ] [k] =    Energy.Matrix[MatrixNumber][ Energy.RowCounter[MatrixNumber]-1 ] [k];
    362362};
    363363
     
    369369void CreateMinimumForce(class MatrixContainer &Force, int MatrixNumber)
    370370{
    371   for (int l=Force.ColumnCounter;l--;)
    372     Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.;
    373   for (int l=5;l<Force.ColumnCounter;l+=3) {
    374     double stored = 0;
    375     int k=0;
    376     do {
    377       for (int m=NDIM;m--;) {
    378         stored += Force.Matrix[MatrixNumber][ k ][l+m]
    379               * Force.Matrix[MatrixNumber][ k ][l+m];
    380         Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m]  = Force.Matrix[MatrixNumber][ k ][l+m];
    381       }
    382       k++;
    383     } while ((fabs(stored) < MYEPSILON) && (k<Force.RowCounter[MatrixNumber]));
    384     for (;k<Force.RowCounter[MatrixNumber];k++) {
    385       double tmp = 0;
    386       for (int m=NDIM;m--;)
    387         tmp += Force.Matrix[MatrixNumber][ k ][l+m]
    388               * Force.Matrix[MatrixNumber][ k ][l+m];
    389       if ((fabs(tmp) > MYEPSILON) && (tmp < stored)) {  // current force is greater than stored
    390         for (int m=NDIM;m--;)
    391           Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m]  = Force.Matrix[MatrixNumber][ k ][l+m];
    392         stored = tmp;
    393       }
    394     }
    395   }
     371        for (int l=Force.ColumnCounter;l--;)
     372                Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.;
     373        for (int l=5;l<Force.ColumnCounter;l+=3) {
     374                double stored = 0;
     375                int k=0;
     376                do {
     377                        for (int m=NDIM;m--;) {
     378                                stored += Force.Matrix[MatrixNumber][ k ][l+m]
     379                                                        * Force.Matrix[MatrixNumber][ k ][l+m];
     380                                Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m]       = Force.Matrix[MatrixNumber][ k ][l+m];
     381                        }
     382                        k++;
     383                } while ((fabs(stored) < MYEPSILON) && (k<Force.RowCounter[MatrixNumber]));
     384                for (;k<Force.RowCounter[MatrixNumber];k++) {
     385                        double tmp = 0;
     386                        for (int m=NDIM;m--;)
     387                                tmp += Force.Matrix[MatrixNumber][ k ][l+m]
     388                                                        * Force.Matrix[MatrixNumber][ k ][l+m];
     389                        if ((fabs(tmp) > MYEPSILON) && (tmp < stored)) {        // current force is greater than stored
     390                                for (int m=NDIM;m--;)
     391                                        Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m]       = Force.Matrix[MatrixNumber][ k ][l+m];
     392                                stored = tmp;
     393                        }
     394                }
     395        }
    396396};
    397397
     
    399399 * Results are stored in the matrix ForceMatrix::MatrixCounter of \a Force.
    400400 * \param Force ForceMatrix class containing matrix values
    401   * \param MatrixNumber the index for the ForceMatrix::matrix array
     401        * \param MatrixNumber the index for the ForceMatrix::matrix array
    402402 */
    403403void CreateMeanForce(class MatrixContainer &Force, int MatrixNumber)
    404404{
    405   int divisor = 0;
    406   for (int l=Force.ColumnCounter;l--;)
    407     Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.;
    408   for (int l=5;l<Force.ColumnCounter;l+=3) {
    409     double tmp = 0;
    410     for (int k=Force.RowCounter[MatrixNumber];k--;) {
    411       double norm = 0.;
    412       for (int m=NDIM;m--;)
    413         norm += Force.Matrix[MatrixNumber][ k ][l+m]
    414               * Force.Matrix[MatrixNumber][ k ][l+m];
    415       tmp += sqrt(norm);
    416       if (fabs(norm) > MYEPSILON) divisor++;
    417     }
    418     tmp /= (double)divisor;
    419     Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = tmp;
    420   }
     405        int divisor = 0;
     406        for (int l=Force.ColumnCounter;l--;)
     407                Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.;
     408        for (int l=5;l<Force.ColumnCounter;l+=3) {
     409                double tmp = 0;
     410                for (int k=Force.RowCounter[MatrixNumber];k--;) {
     411                        double norm = 0.;
     412                        for (int m=NDIM;m--;)
     413                                norm += Force.Matrix[MatrixNumber][ k ][l+m]
     414                                                        * Force.Matrix[MatrixNumber][ k ][l+m];
     415                        tmp += sqrt(norm);
     416                        if (fabs(norm) > MYEPSILON) divisor++;
     417                }
     418                tmp /= (double)divisor;
     419                Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = tmp;
     420        }
    421421};
    422422
     
    428428void CreateMaximumForce(class MatrixContainer &Force, int MatrixNumber)
    429429{
    430   for (int l=5;l<Force.ColumnCounter;l+=3) {
    431     double stored = 0;
    432     for (int k=Force.RowCounter[MatrixNumber];k--;) {
    433       double tmp = 0;
    434       for (int m=NDIM;m--;)
    435         tmp += Force.Matrix[MatrixNumber][ k ][l+m]
    436               * Force.Matrix[MatrixNumber][ k ][l+m];
    437       if (tmp > stored) {  // current force is greater than stored
    438         for (int m=NDIM;m--;)
    439           Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m]  = Force.Matrix[MatrixNumber][ k ][l+m];
    440         stored = tmp;
    441       }
    442     }
    443   }
     430        for (int l=5;l<Force.ColumnCounter;l+=3) {
     431                double stored = 0;
     432                for (int k=Force.RowCounter[MatrixNumber];k--;) {
     433                        double tmp = 0;
     434                        for (int m=NDIM;m--;)
     435                                tmp += Force.Matrix[MatrixNumber][ k ][l+m]
     436                                                        * Force.Matrix[MatrixNumber][ k ][l+m];
     437                        if (tmp > stored) {     // current force is greater than stored
     438                                for (int m=NDIM;m--;)
     439                                        Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m]       = Force.Matrix[MatrixNumber][ k ][l+m];
     440                                stored = tmp;
     441                        }
     442                }
     443        }
    444444};
    445445
     
    450450void CreateSameForce(class MatrixContainer &Force, int MatrixNumber)
    451451{
    452   // does nothing
     452        // does nothing
    453453};
    454454
     
    460460void CreateVectorSumForce(class MatrixContainer &Force, int MatrixNumber)
    461461{
    462   for (int l=Force.ColumnCounter;l--;)
    463     Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.;
    464   for (int l=0;l<Force.ColumnCounter;l++) {
    465     for (int k=Force.RowCounter[MatrixNumber];k--;)
    466       Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] += Force.Matrix[MatrixNumber][k][l];
    467   }
     462        for (int l=Force.ColumnCounter;l--;)
     463                Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.;
     464        for (int l=0;l<Force.ColumnCounter;l++) {
     465                for (int k=Force.RowCounter[MatrixNumber];k--;)
     466                        Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] += Force.Matrix[MatrixNumber][k][l];
     467        }
    468468};
    469469
     
    472472 * \param *key position of key
    473473 * \param *logscale axis for logscale
    474  * \param *extraline extra set lines if desired 
     474 * \param *extraline extra set lines if desired
    475475 * \param mxtics small tics at ...
    476476 * \param xtics large tics at ...
    477  * \param *xlabel label for x axis 
     477 * \param *xlabel label for x axis
    478478 * \param *ylabel label for y axis
    479  */ 
     479 */
    480480void CreatePlotHeader(ofstream &output, const char *prefix, const int keycolumns, const char *key, const char *logscale, const char *extraline, const int mxtics, const int xtics, const char *xlabel, const char *ylabel)
    481481{
    482   //output << "#!/home/heber/build/pyxplot/pyxplot" << endl << endl;
    483   output << "reset" << endl;
    484   output << "set keycolumns "<< keycolumns << endl;
    485   output << "set key " << key << endl;
    486   output << "set mxtics "<< mxtics << endl;
    487   output << "set xtics "<< xtics << endl;
    488   if (logscale != NULL)
    489     output << "set logscale " << logscale << endl;
    490   if (extraline != NULL)
    491     output << extraline << endl;
    492   output << "set xlabel '" << xlabel << "'" << endl;
    493   output << "set ylabel '" << ylabel << "'" << endl;
    494   output << "set terminal eps color" << endl;
    495   output << "set output '"<< prefix << ".eps'" << endl;
     482        //output << "#!/home/heber/build/pyxplot/pyxplot" << endl << endl;
     483        output << "reset" << endl;
     484        output << "set keycolumns "<< keycolumns << endl;
     485        output << "set key " << key << endl;
     486        output << "set mxtics "<< mxtics << endl;
     487        output << "set xtics "<< xtics << endl;
     488        if (logscale != NULL)
     489                output << "set logscale " << logscale << endl;
     490        if (extraline != NULL)
     491                output << extraline << endl;
     492        output << "set xlabel '" << xlabel << "'" << endl;
     493        output << "set ylabel '" << ylabel << "'" << endl;
     494        output << "set terminal eps color" << endl;
     495        output << "set output '"<< prefix << ".eps'" << endl;
    496496};
    497497
     
    506506 * \param mxtics small tics at ...
    507507 * \param xtics large tics at ...
    508  * \param xlabel label for x axis 
     508 * \param xlabel label for x axis
    509509 * \param xlabel label for x axis
    510510 * \param *xrange xrange
     
    514514 * \param (*CreatePlotLines) function reference that writes a single plot line
    515515 * \return true if file was written successfully
    516  */   
     516 */
    517517bool CreatePlotOrder(class MatrixContainer &Matrix, const class KeySetsContainer &KeySet, const char *dir, const char *prefix, const int keycolumns, const char *key, const char *logscale, const char *extraline, const int mxtics, const int xtics, const char *xlabel, const char *ylabel, const char *xrange, const char *yrange, const char *xargument, const char *uses, void (*CreatePlotLines)(ofstream &, class MatrixContainer &, const char *, const char *, const char *))
    518518{
    519   stringstream filename;
    520   ofstream output;
    521 
    522   filename << prefix << ".pyx";
    523   if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
    524   CreatePlotHeader(output, prefix, keycolumns, key, logscale, extraline, mxtics, xtics, xlabel, ylabel);
    525   output << "plot " << xrange << " " << yrange << " \\" << endl;
    526   CreatePlotLines(output, Matrix, prefix, xargument, uses);
    527   output.close(); 
    528   return true;
     519        stringstream filename;
     520        ofstream output;
     521
     522        filename << prefix << ".pyx";
     523        if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
     524        CreatePlotHeader(output, prefix, keycolumns, key, logscale, extraline, mxtics, xtics, xlabel, ylabel);
     525        output << "plot " << xrange << " " << yrange << " \\" << endl;
     526        CreatePlotLines(output, Matrix, prefix, xargument, uses);
     527        output.close();
     528        return true;
    529529};
    530530
     
    538538void AbsEnergyPlotLine(ofstream &output, class MatrixContainer &Energy, const char *prefix, const char *xargument, const char *uses)
    539539{
    540   stringstream line(Energy.Header);
    541   string token;
    542 
    543   getline(line, token, '\t');
    544   for (int i=2; i<= Energy.ColumnCounter;i++) {
    545     getline(line, token, '\t');
    546     while (token[0] == ' ') // remove leading white spaces
    547       token.erase(0,1);
    548     output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(abs($" << i+2 << ")) " << uses;
    549     if (i != (Energy.ColumnCounter))
    550       output << ", \\";
    551     output << endl;
    552   }
     540        stringstream line(Energy.Header);
     541        string token;
     542
     543        getline(line, token, '\t');
     544        for (int i=2; i<= Energy.ColumnCounter;i++) {
     545                getline(line, token, '\t');
     546                while (token[0] == ' ') // remove leading white spaces
     547                        token.erase(0,1);
     548                output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(abs($" << i+2 << ")) " << uses;
     549                if (i != (Energy.ColumnCounter))
     550                        output << ", \\";
     551                output << endl;
     552        }
    553553};
    554554
     
    562562void EnergyPlotLine(ofstream &output, class MatrixContainer &Energy, const char *prefix, const char *xargument, const char *uses)
    563563{
    564   stringstream line(Energy.Header);
    565   string token;
    566 
    567   getline(line, token, '\t');
    568   for (int i=1; i<= Energy.ColumnCounter;i++) {
    569     getline(line, token, '\t');
    570     while (token[0] == ' ') // remove leading white spaces
    571       token.erase(0,1);
    572     output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":" << i+2 << " " << uses;
    573     if (i != (Energy.ColumnCounter))
    574       output << ", \\";
    575     output << endl;
    576   }
     564        stringstream line(Energy.Header);
     565        string token;
     566
     567        getline(line, token, '\t');
     568        for (int i=1; i<= Energy.ColumnCounter;i++) {
     569                getline(line, token, '\t');
     570                while (token[0] == ' ') // remove leading white spaces
     571                        token.erase(0,1);
     572                output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":" << i+2 << " " << uses;
     573                if (i != (Energy.ColumnCounter))
     574                        output << ", \\";
     575                output << endl;
     576        }
    577577};
    578578
     
    586586void ForceMagnitudePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses)
    587587{
    588   stringstream line(Force.Header);
    589   string token;
    590 
    591   getline(line, token, '\t');
    592   getline(line, token, '\t');
    593   getline(line, token, '\t');
    594   getline(line, token, '\t');
    595   getline(line, token, '\t');
    596   for (int i=7; i< Force.ColumnCounter;i+=NDIM) {
    597     getline(line, token, '\t');
    598     while (token[0] == ' ') // remove leading white spaces
    599       token.erase(0,1);
    600     token.erase(token.length(), 1);  // kill residual index char (the '0')
    601     output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(sqrt($" << i+1 << "*$" << i+1 << "+$" << i+2 << "*$" << i+2 << "+$" << i+3 << "*$" << i+3 << ")) " << uses;
    602     if (i != (Force.ColumnCounter-1))
    603       output << ", \\";
    604     output << endl;
    605     getline(line, token, '\t');
    606     getline(line, token, '\t');
    607   }
     588        stringstream line(Force.Header);
     589        string token;
     590
     591        getline(line, token, '\t');
     592        getline(line, token, '\t');
     593        getline(line, token, '\t');
     594        getline(line, token, '\t');
     595        getline(line, token, '\t');
     596        for (int i=7; i< Force.ColumnCounter;i+=NDIM) {
     597                getline(line, token, '\t');
     598                while (token[0] == ' ') // remove leading white spaces
     599                        token.erase(0,1);
     600                token.erase(token.length(), 1); // kill residual index char (the '0')
     601                output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(sqrt($" << i+1 << "*$" << i+1 << "+$" << i+2 << "*$" << i+2 << "+$" << i+3 << "*$" << i+3 << ")) " << uses;
     602                if (i != (Force.ColumnCounter-1))
     603                        output << ", \\";
     604                output << endl;
     605                getline(line, token, '\t');
     606                getline(line, token, '\t');
     607        }
    608608};
    609609
     
    617617void AbsFirstForceValuePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses)
    618618{
    619   stringstream line(Force.Header);
    620   string token;
    621 
    622   getline(line, token, '\t');
    623   getline(line, token, '\t');
    624   getline(line, token, '\t');
    625   getline(line, token, '\t');
    626   getline(line, token, '\t');
    627   for (int i=7; i< Force.ColumnCounter;i+=NDIM) {
    628     getline(line, token, '\t');
    629     while (token[0] == ' ') // remove leading white spaces
    630       token.erase(0,1);
    631     token.erase(token.length(), 1);  // kill residual index char (the '0')
    632     output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(abs($" << i+1 << ")) " << uses;
    633     if (i != (Force.ColumnCounter-1))
    634       output << ", \\";
    635     output << endl;
    636     getline(line, token, '\t');
    637     getline(line, token, '\t');
    638   }
     619        stringstream line(Force.Header);
     620        string token;
     621
     622        getline(line, token, '\t');
     623        getline(line, token, '\t');
     624        getline(line, token, '\t');
     625        getline(line, token, '\t');
     626        getline(line, token, '\t');
     627        for (int i=7; i< Force.ColumnCounter;i+=NDIM) {
     628                getline(line, token, '\t');
     629                while (token[0] == ' ') // remove leading white spaces
     630                        token.erase(0,1);
     631                token.erase(token.length(), 1); // kill residual index char (the '0')
     632                output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(abs($" << i+1 << ")) " << uses;
     633                if (i != (Force.ColumnCounter-1))
     634                        output << ", \\";
     635                output << endl;
     636                getline(line, token, '\t');
     637                getline(line, token, '\t');
     638        }
    639639};
    640640
     
    648648void BoxesForcePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses)
    649649{
    650   stringstream line(Force.Header);
    651   char *fillcolor[5] = {"black", "red", "blue", "green", "cyan"};
    652   string token;
    653 
    654   getline(line, token, '\t');
    655   getline(line, token, '\t');
    656   getline(line, token, '\t');
    657   getline(line, token, '\t');
    658   getline(line, token, '\t');
    659   for (int i=7; i< Force.ColumnCounter;i+=NDIM) {
    660     getline(line, token, '\t');
    661     while (token[0] == ' ') // remove leading white spaces
    662       token.erase(0,1);
    663     token.erase(token.length(), 1);  // kill residual index char (the '0')
    664     output << "'" << prefix << ".dat' title '" << token << "' using ($" << xargument << "+" << fixed << setprecision(1) << (double)((i-7)/3)*0.2 << "):(sqrt($" << i+1 << "*$" << i+1 << "+$" << i+2 << "*$" << i+2 << "+$" << i+3 << "*$" << i+3 << ")) " << uses << " " << fillcolor[(i-7)/3];
    665     if (i != (Force.ColumnCounter-1))
    666       output << ", \\";
    667     output << endl;
    668     getline(line, token, '\t');
    669     getline(line, token, '\t');
    670   }
     650        stringstream line(Force.Header);
     651        char *fillcolor[5] = {"black", "red", "blue", "green", "cyan"};
     652        string token;
     653
     654        getline(line, token, '\t');
     655        getline(line, token, '\t');
     656        getline(line, token, '\t');
     657        getline(line, token, '\t');
     658        getline(line, token, '\t');
     659        for (int i=7; i< Force.ColumnCounter;i+=NDIM) {
     660                getline(line, token, '\t');
     661                while (token[0] == ' ') // remove leading white spaces
     662                        token.erase(0,1);
     663                token.erase(token.length(), 1); // kill residual index char (the '0')
     664                output << "'" << prefix << ".dat' title '" << token << "' using ($" << xargument << "+" << fixed << setprecision(1) << (double)((i-7)/3)*0.2 << "):(sqrt($" << i+1 << "*$" << i+1 << "+$" << i+2 << "*$" << i+2 << "+$" << i+3 << "*$" << i+3 << ")) " << uses << " " << fillcolor[(i-7)/3];
     665                if (i != (Force.ColumnCounter-1))
     666                        output << ", \\";
     667                output << endl;
     668                getline(line, token, '\t');
     669                getline(line, token, '\t');
     670        }
    671671};
    672672
     
    680680void BoxesFirstForceValuePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses)
    681681{
    682   stringstream line(Force.Header);
    683   char *fillcolor[5] = {"black", "red", "blue", "green", "cyan"};
    684   string token;
    685 
    686   getline(line, token, '\t');
    687   getline(line, token, '\t');
    688   getline(line, token, '\t');
    689   getline(line, token, '\t');
    690   getline(line, token, '\t');
    691   for (int i=7; i< Force.ColumnCounter;i+=NDIM) {
    692     getline(line, token, '\t');
    693     while (token[0] == ' ') // remove leading white spaces
    694       token.erase(0,1);
    695     token.erase(token.length(), 1);  // kill residual index char (the '0')
    696     output << "'" << prefix << ".dat' title '" << token << "' using ($" << xargument << "+" << fixed << setprecision(1) << (double)((i-7)/3)*0.2 << "):" << i+1 << " " << uses << " " << fillcolor[(i-7)/3];
    697     if (i != (Force.ColumnCounter-1))
    698       output << ", \\";
    699     output << endl;
    700     getline(line, token, '\t');
    701     getline(line, token, '\t');
    702   }
    703 };
     682        stringstream line(Force.Header);
     683        char *fillcolor[5] = {"black", "red", "blue", "green", "cyan"};
     684        string token;
     685
     686        getline(line, token, '\t');
     687        getline(line, token, '\t');
     688        getline(line, token, '\t');
     689        getline(line, token, '\t');
     690        getline(line, token, '\t');
     691        for (int i=7; i< Force.ColumnCounter;i+=NDIM) {
     692                getline(line, token, '\t');
     693                while (token[0] == ' ') // remove leading white spaces
     694                        token.erase(0,1);
     695                token.erase(token.length(), 1); // kill residual index char (the '0')
     696                output << "'" << prefix << ".dat' title '" << token << "' using ($" << xargument << "+" << fixed << setprecision(1) << (double)((i-7)/3)*0.2 << "):" << i+1 << " " << uses << " " << fillcolor[(i-7)/3];
     697                if (i != (Force.ColumnCounter-1))
     698                        output << ", \\";
     699                output << endl;
     700                getline(line, token, '\t');
     701                getline(line, token, '\t');
     702        }
     703};
  • src/datacreator.hpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    11/** \file datacreator.cpp
    22 *
    3  * Definitions of assisting functions in creating data and plot files. 
    4  *   
     3 * Definitions of assisting functions in creating data and plot files.
     4 *
    55 */
    66
     
    1212//============================ INCLUDES ===========================
    1313
    14 #include "helpers.hpp" 
     14#include "helpers.hpp"
    1515#include "parser.hpp"
    1616
     
    2020bool AppendOutputFile(ofstream &output, const char *dir, const char *filename);
    2121
    22 bool CreateDataEnergyOrder(class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); 
    23 bool CreateDataDeltaEnergyOrder(class EnergyMatrix &Energy, class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); 
     22bool CreateDataEnergyOrder(class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum);
     23bool CreateDataDeltaEnergyOrder(class EnergyMatrix &Energy, class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum);
    2424bool CreateDataForcesOrder(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateForce)(class MatrixContainer &, int));
    2525bool CreateDataForcesOrderPerAtom(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum);
    2626bool CreateDataDeltaForcesOrder(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateForce)(class MatrixContainer &, int));
    27 bool CreateDataDeltaForcesOrderPerAtom(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); 
     27bool CreateDataDeltaForcesOrderPerAtom(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum);
    2828bool CreateDataFragment(class MatrixContainer &ForceFragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateForce)(class MatrixContainer &, int));
    2929bool CreateDataFragmentOrder(class MatrixContainer &Fragment, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateFragmentOrder)(class MatrixContainer &, class KeySetsContainer &, int));
  • src/defs.hpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    1010using namespace std;
    1111
    12 #define MYEPSILON 1e-13  //!< machine epsilon precision
    13 #define NDIM  3  //!< number of spatial dimensions
    14 #define MAX_ELEMENTS 128  //!< maximum number of elements for certain lookup tables
    15 #define AtomicLengthToAngstroem  0.52917721 //!< conversion factor from atomic length/bohrradius to angstroem
    16 #define BONDTHRESHOLD 0.5  //!< CSD threshold in bond check which is the width of the interval whose center is the sum of the covalent radii
    17 #define AtomicEnergyToKelvin 315774.67  //!< conversion factor from atomic energy to kelvin via boltzmann factor
     12#define MYEPSILON 1e-13  //!< machine epsilon precision
     13#define NDIM    3        //!< number of spatial dimensions
     14#define MAX_ELEMENTS 128        //!< maximum number of elements for certain lookup tables
     15#define AtomicLengthToAngstroem 0.52917721 //!< conversion factor from atomic length/bohrradius to angstroem
     16#define BONDTHRESHOLD 0.5        //!< CSD threshold in bond check which is the width of the interval whose center is the sum of the covalent radii
     17#define AtomicEnergyToKelvin 315774.67  //!< conversion factor from atomic energy to kelvin via boltzmann factor
    1818#define VERSIONSTRING "v1.0"
    1919
     
    2424enum EdgeType { Undetermined, TreeEdge, BackEdge }; //!< edge type in a graph after Depth-First-Search analysis.
    2525
    26 enum Shading { white, lightgray, darkgray, black };  //!< color in Breadth-First-Search analysis
     26enum Shading { white, lightgray, darkgray, black };     //!< color in Breadth-First-Search analysis
    2727
    28 //enum CutCyclicBond { KeepBond,  SaturateBond }; //!< Saturation scheme either atom- or bondwise
     28//enum CutCyclicBond { KeepBond,        SaturateBond }; //!< Saturation scheme either atom- or bondwise
    2929
    3030// Specifting whether a value in the parameter file must be specified or is optional
    31 enum necessity { optional,    //!< parameter is optional, if not given sensible value is chosen
    32                  critical    //!< parameter must be given or programme won't initiate
    33               };
     31enum necessity { optional,              //!< parameter is optional, if not given sensible value is chosen
     32                                                                 critical                //!< parameter must be given or programme won't initiate
     33                                                        };
    3434
    3535// Specifying the status of the on command line given config file
     
    4343
    4444// various standard filenames
    45 #define DEFAULTCONFIG "main_pcp_linux"    //!< default filename of config file
    46 #define CONVEXENVELOPE "ConvexEnvelope.dat"    //!< default filename of convex envelope tecplot data file
    47 #define KEYSETFILE "KeySets.dat"    //!< default filename of BOSSANOVA key sets file
    48 #define ADJACENCYFILE "Adjacency.dat"    //!< default filename of BOSSANOVA adjacancy file
    49 #define TEFACTORSFILE "TE-Factors.dat"    //!< default filename of BOSSANOVA total energy factors file
    50 #define FORCESFILE "Forces-Factors.dat"    //!< default filename of BOSSANOVA force factors file
    51 #define HCORRECTIONSUFFIX "Hcorrection.dat"    //!< default filename of BOSSANOVA H correction file (unwanted saturation interaction)
    52 #define FITCONSTANTSUFFIX "FitConstant.dat"  //!< suffix of default filename of BOSSANOVA fit constants file (unwanted saturation interaction)
    53 #define SHIELDINGSUFFIX "sigma_all.csv"                //!< default filename of BOSSANOVA shieldings file
    54 #define SHIELDINGPASSUFFIX "sigma_all_PAS.csv"                //!< default filename of BOSSANOVA shieldings PAS file
    55 #define ORDERATSITEFILE "OrderAtSite.dat"    //!< default filename of BOSSANOVA Bond Order at each atom file
    56 #define ENERGYPERFRAGMENT "EnergyPerFragment"    //!< default filename of BOSSANOVA Energy contribution Per Fragment file
    57 #define FRAGMENTPREFIX "BondFragment"    //!< default filename prefix of BOSSANOVA fragment config and directories
    58 #define STANDARDCONFIG "unknown.conf"    //!< default filename of standard config file
    59 #define STANDARDELEMENTSDB "elements.db"    //!< default filename of elements data base with masses, Z, VanDerWaals radii, ...
    60 #define STANDARDVALENCEDB "valence.db"    //!< default filename of valence number per element database
    61 #define STANDARDORBITALDB "orbitals.db"    //!< default filename of orbitals per element database
    62 #define STANDARDHBONDDISTANCEDB "Hbonddistance.db"    //!< default filename of typial bond distance to hydrogen database
    63 #define STANDARDHBONDANGLEDB "Hbondangle.db"    //!< default filename of typial bond angle to hydrogen database
     45#define DEFAULTCONFIG "main_pcp_linux"          //!< default filename of config file
     46#define CONVEXENVELOPE "ConvexEnvelope.dat"             //!< default filename of convex envelope tecplot data file
     47#define KEYSETFILE "KeySets.dat"                //!< default filename of BOSSANOVA key sets file
     48#define ADJACENCYFILE "Adjacency.dat"           //!< default filename of BOSSANOVA adjacancy file
     49#define TEFACTORSFILE "TE-Factors.dat"          //!< default filename of BOSSANOVA total energy factors file
     50#define FORCESFILE "Forces-Factors.dat"         //!< default filename of BOSSANOVA force factors file
     51#define HCORRECTIONSUFFIX "Hcorrection.dat"             //!< default filename of BOSSANOVA H correction file (unwanted saturation interaction)
     52#define FITCONSTANTSUFFIX "FitConstant.dat"      //!< suffix of default filename of BOSSANOVA fit constants file (unwanted saturation interaction)
     53#define SHIELDINGSUFFIX "sigma_all.csv"                                                         //!< default filename of BOSSANOVA shieldings file
     54#define SHIELDINGPASSUFFIX "sigma_all_PAS.csv"                                                          //!< default filename of BOSSANOVA shieldings PAS file
     55#define ORDERATSITEFILE "OrderAtSite.dat"               //!< default filename of BOSSANOVA Bond Order at each atom file
     56#define ENERGYPERFRAGMENT "EnergyPerFragment"           //!< default filename of BOSSANOVA Energy contribution Per Fragment file
     57#define FRAGMENTPREFIX "BondFragment"           //!< default filename prefix of BOSSANOVA fragment config and directories
     58#define STANDARDCONFIG "unknown.conf"           //!< default filename of standard config file
     59#define STANDARDELEMENTSDB "elements.db"                //!< default filename of elements data base with masses, Z, VanDerWaals radii, ...
     60#define STANDARDVALENCEDB "valence.db"          //!< default filename of valence number per element database
     61#define STANDARDORBITALDB "orbitals.db"         //!< default filename of orbitals per element database
     62#define STANDARDHBONDDISTANCEDB "Hbonddistance.db"              //!< default filename of typial bond distance to hydrogen database
     63#define STANDARDHBONDANGLEDB "Hbondangle.db"            //!< default filename of typial bond angle to hydrogen database
    6464
    6565// some values
     
    6868
    6969
    70 #define UPDATECOUNT 10  //!< update ten sites per BOSSANOVA interval
     70#define UPDATECOUNT 10  //!< update ten sites per BOSSANOVA interval
    7171
    7272#endif /*DEFS_HPP_*/
  • src/element.cpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    1212 */
    1313element::element() {
    14   Z = -1;
    15   No = -1;
    16   previous = NULL;
    17   next = NULL;
    18   sort = NULL;
     14        Z = -1;
     15        No = -1;
     16        previous = NULL;
     17        next = NULL;
     18        sort = NULL;
    1919};
    2020
     
    2828bool element::Output(ofstream *out) const
    2929{
    30   if (out != NULL) {
    31     *out << name << "\t" << symbol << "\t" << period << "\t" << group << "\t" << block << "\t" << Z << "\t" << mass << "\t" << CovalentRadius << "\t" << VanDerWaalsRadius << endl;
    32     //*out << Z << "\t"  << fixed << setprecision(11) << showpoint << mass << "g/mol\t" << name << "\t" << symbol << "\t" << endl;
    33     return true;
    34   } else
    35     return false;
     30        if (out != NULL) {
     31                *out << name << "\t" << symbol << "\t" << period << "\t" << group << "\t" << block << "\t" << Z << "\t" << mass << "\t" << CovalentRadius << "\t" << VanDerWaalsRadius << endl;
     32                //*out << Z << "\t"     << fixed << setprecision(11) << showpoint << mass << "g/mol\t" << name << "\t" << symbol << "\t" << endl;
     33                return true;
     34        } else
     35                return false;
    3636};
    3737
    3838/** Prints element data to \a *out.
    3939 * \param *out outstream
    40  * \param No  cardinal number of element
     40 * \param No    cardinal number of element
    4141 * \param NoOfAtoms total number of atom of this element type
    4242 */
    4343bool element::Checkout(ofstream *out, const int Number, const int NoOfAtoms) const
    4444{
    45   if (out != NULL) {
    46     *out << "Ion_Type" << Number << "\t" << NoOfAtoms << "\t" << Z << "\t1.0\t3\t3\t" << fixed << setprecision(11) << showpoint << mass << "\t" << name << "\t" << symbol <<endl;
    47     return true;
    48   } else
    49     return false;
     45        if (out != NULL) {
     46                *out << "Ion_Type" << Number << "\t" << NoOfAtoms << "\t" << Z << "\t1.0\t3\t3\t" << fixed << setprecision(11) << showpoint << mass << "\t" << name << "\t" << symbol <<endl;
     47                return true;
     48        } else
     49                return false;
    5050};
  • src/elements.db

    • Property mode changed from 100644 to 100755
  • src/graph.cpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    11/** \file graph.cpp
    2  * 
     2 *
    33 * Function implementations for the class graph.
    4  * 
     4 *
    55 */
    66
     
    1515
    1616
    17  
  • src/helpers.cpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    11/** \file helpers.cpp
    22 *
    3  * Implementation of some auxiliary functions for memory dis-/allocation and so on 
     3 * Implementation of some auxiliary functions for memory dis-/allocation and so on
    44 */
    55
     
    1515double ask_value(const char *text)
    1616{
    17   double test = 0.1439851348959832147598734598273456723948652983045928346598365;
    18   do {
    19     cout << Verbose(0) << text;
    20     cin >> test;
    21   } while (test == 0.1439851348959832147598734598273456723948652983045928346598365);
    22   return test;   
     17        double test = 0.1439851348959832147598734598273456723948652983045928346598365;
     18        do {
     19                cout << Verbose(0) << text;
     20                cin >> test;
     21        } while (test == 0.1439851348959832147598734598273456723948652983045928346598365);
     22        return test;
    2323};
    2424
     
    2929#ifdef HAVE_DEBUG
    3030void debug_in(const char *output, const char *file, const int line) {
    31   if (output) fprintf(stderr,"DEBUG: in %s at line %i: %s\n", file, line, output);
     31        if (output) fprintf(stderr,"DEBUG: in %s at line %i: %s\n", file, line, output);
    3232}
    3333#else
    34 void debug_in(const char *output, const char *file, const int line) {}  // print nothing
     34void debug_in(const char *output, const char *file, const int line) {}  // print nothing
    3535#endif
    3636
     
    4040 * \return pointer to memory range
    4141 */
    42 void * Malloc(size_t size, const char* output) 
     42void * Malloc(size_t size, const char* output)
    4343{
    44   void *buffer = NULL;
    45   buffer = (void *)malloc(size); // alloc
    46   if (buffer == NULL)
    47     cout << Verbose(0) << "Malloc failed - pointer is NULL: " << output << endl;
    48   return(buffer);
     44        void *buffer = NULL;
     45        buffer = (void *)malloc(size); // alloc
     46        if (buffer == NULL)
     47                cout << Verbose(0) << "Malloc failed - pointer is NULL: " << output << endl;
     48        return(buffer);
    4949};
    5050
     
    5454 * \return pointer to memory range
    5555 */
    56 void * Calloc(size_t size, const char* output) 
     56void * Calloc(size_t size, const char* output)
    5757{
    58   void *buffer = NULL;
    59   buffer = (void *)calloc(size, (size_t)0); // alloc
    60   if (buffer == NULL)
    61     cout << Verbose(0) << "Calloc failed - pointer is NULL: " << output << endl;
    62   return(buffer);
     58        void *buffer = NULL;
     59        buffer = (void *)calloc(size, (size_t)0); // alloc
     60        if (buffer == NULL)
     61                cout << Verbose(0) << "Calloc failed - pointer is NULL: " << output << endl;
     62        return(buffer);
    6363};
    6464
     
    6969 * \return pointer to memory range
    7070 */
    71 void * ReAlloc(void * OldPointer, size_t size, const char* output) 
     71void * ReAlloc(void * OldPointer, size_t size, const char* output)
    7272{
    73   void *buffer = NULL;
    74   if (OldPointer == NULL)
    75         //cout << Verbose(0) << "ReAlloc impossible - old is NULL: " << output << endl;
    76     buffer = (void *)malloc(size); // malloc
    77   else
    78     buffer = (void *)realloc(OldPointer, size); // realloc
    79   if (buffer == NULL)
    80     cout << Verbose(0) << "ReAlloc failed - new is NULL: " << output << endl;
    81   return(buffer);
     73        void *buffer = NULL;
     74        if (OldPointer == NULL)
     75                //cout << Verbose(0) << "ReAlloc impossible - old is NULL: " << output << endl;
     76                buffer = (void *)malloc(size); // malloc
     77        else
     78                buffer = (void *)realloc(OldPointer, size); // realloc
     79        if (buffer == NULL)
     80                cout << Verbose(0) << "ReAlloc failed - new is NULL: " << output << endl;
     81        return(buffer);
    8282};
    8383
     
    8686 * \param *output message if free fails
    8787 */
    88 void Free(void ** buffer, const char* output) 
     88void Free(void ** buffer, const char* output)
    8989{
    90   if (*buffer == NULL) {
    91     //cout << Verbose(5) << "Free not necesary: " << output << endl;
    92   } else {
    93     free(*buffer);
    94     *buffer = NULL;
    95   }
     90        if (*buffer == NULL) {
     91                //cout << Verbose(5) << "Free not necesary: " << output << endl;
     92        } else {
     93                free(*buffer);
     94                *buffer = NULL;
     95        }
    9696};
    9797
     
    101101 * \return pointer to string array
    102102 */
    103 char* MallocString(size_t size, const char* output) 
     103char* MallocString(size_t size, const char* output)
    104104{
    105   size_t i;
    106   char *buffer;
    107   buffer = (char *)malloc(sizeof(char) * (size+1)); // alloc
    108   if (buffer == NULL)
    109     cout << Verbose(0) << output << endl;
    110   for (i=size;i--;)  // reset
    111     buffer[i] = i % 2 == 0 ? 'p': 'c';
    112   buffer[size] = '\0'; // and set length marker on its end
    113   return(buffer);
     105        size_t i;
     106        char *buffer;
     107        buffer = (char *)malloc(sizeof(char) * (size+1)); // alloc
     108        if (buffer == NULL)
     109                cout << Verbose(0) << output << endl;
     110        for (i=size;i--;)       // reset
     111                buffer[i] = i % 2 == 0 ? 'p': 'c';
     112        buffer[size] = '\0'; // and set length marker on its end
     113        return(buffer);
    114114}
    115115
     
    121121void bound(double *b, double lower_bound, double upper_bound)
    122122{
    123   double step = (upper_bound - lower_bound);
    124   while (*b >= upper_bound)
    125     *b -= step;   
    126   while (*b < lower_bound)
    127     *b += step;   
    128 }; 
     123        double step = (upper_bound - lower_bound);
     124        while (*b >= upper_bound)
     125                *b -= step;
     126        while (*b < lower_bound)
     127                *b += step;
     128};
    129129
    130130/** Flips two doubles.
     
    134134void flip(double *x, double *y)
    135135{
    136   double tmp;
    137   tmp = *x;
    138   *x = *y;
    139   *y = tmp;
     136        double tmp;
     137        tmp = *x;
     138        *x = *y;
     139        *y = tmp;
    140140};
    141141
     
    147147int pot(int base, int n)
    148148{
    149   int res = 1;
    150   int j;
    151   for (j=n;j--;)
    152     res *= base;
    153   return res;
     149        int res = 1;
     150        int j;
     151        for (j=n;j--;)
     152                res *= base;
     153        return res;
    154154};
    155155
     
    161161char *FixedDigitNumber(const int FragmentNumber, const int digits)
    162162{
    163   char *returnstring;
    164   int number = FragmentNumber;
    165   int order = 0;
    166   while (number != 0) { // determine number of digits needed
    167     number = (int)floor(((double)number / 10.));
    168     order++;
    169     //cout << "Number is " << number << ", order is " << order << "." << endl;
    170   }
    171   // allocate string
    172   returnstring = (char *) Malloc(sizeof(char)*(order+2), "MoleculeListClass::CreateFragmentNumberForOutput: *returnstring");
    173   // terminate  and fill string array from end backward
    174   returnstring[order] = '\0';
    175   number = digits;
    176   for (int i=order;i--;) {
    177     returnstring[i] = '0' + (char)(number % 10);
    178     number = (int)floor(((double)number / 10.));
    179   }
    180   //cout << returnstring << endl;
    181   return returnstring;
     163        char *returnstring;
     164        int number = FragmentNumber;
     165        int order = 0;
     166        while (number != 0) { // determine number of digits needed
     167                number = (int)floor(((double)number / 10.));
     168                order++;
     169                //cout << "Number is " << number << ", order is " << order << "." << endl;
     170        }
     171        // allocate string
     172        returnstring = (char *) Malloc(sizeof(char)*(order+2), "MoleculeListClass::CreateFragmentNumberForOutput: *returnstring");
     173        // terminate    and fill string array from end backward
     174        returnstring[order] = '\0';
     175        number = digits;
     176        for (int i=order;i--;) {
     177                returnstring[i] = '0' + (char)(number % 10);
     178                number = (int)floor(((double)number / 10.));
     179        }
     180        //cout << returnstring << endl;
     181        return returnstring;
    182182};
    183183
     
    186186 * \return true - is a number, false - is not a valid number
    187187 */
    188 bool IsValidNumber( const char *string) 
     188bool IsValidNumber( const char *string)
    189189{
    190   int ptr = 0;
    191   if ((string[ptr] == '.') || (string[ptr] == '-')) // number may be negative or start with dot
    192     ptr++;
    193   if ((string[ptr] >= '0') && (string[ptr] <= '9'))
    194     return true;
    195   return false;
     190        int ptr = 0;
     191        if ((string[ptr] == '.') || (string[ptr] == '-')) // number may be negative or start with dot
     192                ptr++;
     193        if ((string[ptr] >= '0') && (string[ptr] <= '9'))
     194                return true;
     195        return false;
    196196};
    197197
  • src/helpers.hpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    11/** \file helpers.hpp
    22 *
    3  * Declaration of some auxiliary functions for memory dis-/allocation and so on 
     3 * Declaration of some auxiliary functions for memory dis-/allocation and so on
    44 */
    55
     
    3838
    3939/* Behandelt aufgetretene Fehler. error ist der Fehlertyp(enum Errors)
    40   void *SpecialData ist ein untypisierter Zeiger auf Spezielle Daten zur Fehlerbehandlung.
    41   Man koennte auch noch einen Zeiger auf eine Funktion uebergeben */
     40        void *SpecialData ist ein untypisierter Zeiger auf Spezielle Daten zur Fehlerbehandlung.
     41        Man koennte auch noch einen Zeiger auf eine Funktion uebergeben */
    4242extern void /*@exits@*/ debug(const char *output);
    43   //__attribute__ ((__return__));
     43        //__attribute__ ((__return__));
    4444#define debug(data) debug_in((data), __FILE__, __LINE__)
    4545
    4646extern void /*@exits@*/ debug_in(const char *output,
    47     const char *file, const int line);
    48   //__attribute__ ((__return__));
     47                const char *file, const int line);
     48        //__attribute__ ((__return__));
    4949
    5050double ask_value(const char *text);
     
    7373template <typename T> bool CreateFatherLookupTable(ofstream *out, T *start, T *end, T **&LookupTable, int count = 0)
    7474{
    75   bool status = true;
    76   T *Walker = NULL;
    77   int AtomNo;
    78  
    79   if (LookupTable != NULL) {
    80     *out << "Pointer for Lookup table is not NULL! Aborting ..." <<endl;
    81     return false;
    82   }
    83  
    84   // count them
    85   if (count == 0) {
    86     Walker = start;
    87     while (Walker->next != end) { // create a lookup table (Atom::nr -> atom) used as a marker table lateron
    88       Walker = Walker->next;
    89       count = (count < Walker->GetTrueFather()->nr) ? Walker->GetTrueFather()->nr : count;
    90     }
    91   }
    92   if (count <= 0) {
    93     *out << "Count of lookup list is 0 or less." << endl;
    94     return false;
    95   }
    96 
    97   // allocat and fill
    98   LookupTable = (T **) Malloc(sizeof(T *)*count, "CreateFatherLookupTable - **LookupTable");
    99   if (LookupTable == NULL) {
    100     cerr << "LookupTable memory allocation failed!" << endl;
    101     status = false;
    102   } else {
    103     for (int i=0;i<count;i++)
    104       LookupTable[i] = NULL;
    105     Walker = start;
    106     while (Walker->next != end) { // create a lookup table (Atom::nr -> atom) used as a marker table lateron
    107       Walker = Walker->next;
    108       AtomNo = Walker->GetTrueFather()->nr;
    109       if ((AtomNo >= 0) && (AtomNo < count)) {
    110         //*out << "Setting LookupTable[" << AtomNo << "] to " << *Walker << endl;
    111         LookupTable[AtomNo] = Walker;
    112       } else {
    113         *out << "Walker " << *Walker << " exceeded range of nuclear ids [0, " << count << ")." << endl;
    114         status = false;
    115         break;
    116       }
    117     }
    118   }
    119  
    120   return status;
     75        bool status = true;
     76        T *Walker = NULL;
     77        int AtomNo;
     78
     79        if (LookupTable != NULL) {
     80                *out << "Pointer for Lookup table is not NULL! Aborting ..." <<endl;
     81                return false;
     82        }
     83
     84        // count them
     85        if (count == 0) {
     86                Walker = start;
     87                while (Walker->next != end) { // create a lookup table (Atom::nr -> atom) used as a marker table lateron
     88                        Walker = Walker->next;
     89                        count = (count < Walker->GetTrueFather()->nr) ? Walker->GetTrueFather()->nr : count;
     90                }
     91        }
     92        if (count <= 0) {
     93                *out << "Count of lookup list is 0 or less." << endl;
     94                return false;
     95        }
     96
     97        // allocat and fill
     98        LookupTable = (T **) Malloc(sizeof(T *)*count, "CreateFatherLookupTable - **LookupTable");
     99        if (LookupTable == NULL) {
     100                cerr << "LookupTable memory allocation failed!" << endl;
     101                status = false;
     102        } else {
     103                for (int i=0;i<count;i++)
     104                        LookupTable[i] = NULL;
     105                Walker = start;
     106                while (Walker->next != end) { // create a lookup table (Atom::nr -> atom) used as a marker table lateron
     107                        Walker = Walker->next;
     108                        AtomNo = Walker->GetTrueFather()->nr;
     109                        if ((AtomNo >= 0) && (AtomNo < count)) {
     110                                //*out << "Setting LookupTable[" << AtomNo << "] to " << *Walker << endl;
     111                                LookupTable[AtomNo] = Walker;
     112                        } else {
     113                                *out << "Walker " << *Walker << " exceeded range of nuclear ids [0, " << count << ")." << endl;
     114                                status = false;
     115                                break;
     116                        }
     117                }
     118        }
     119
     120        return status;
    121121};
    122122
     
    129129template <typename X> void link(X *walker, X *end)
    130130{
    131   X *vorher = end->previous;
    132   if (vorher != NULL)
    133     vorher->next = walker;
    134   end->previous = walker;
    135   walker->previous = vorher;
    136   walker->next = end;
     131        X *vorher = end->previous;
     132        if (vorher != NULL)
     133                vorher->next = walker;
     134        end->previous = walker;
     135        walker->previous = vorher;
     136        walker->next = end;
    137137};
    138138
     
    143143template <typename X> void unlink(X *walker)
    144144{
    145   if (walker->next != NULL)
    146     walker->next->previous = walker->previous;
    147   if (walker->previous != NULL)
    148     walker->previous->next = walker->next;
     145        if (walker->next != NULL)
     146                walker->next->previous = walker->previous;
     147        if (walker->previous != NULL)
     148                walker->previous->next = walker->next;
    149149};
    150150
    151151/** Adds new item before an item \a *end in a list.
    152  * \param *pointer  item to be added
    153  * \param *end  end of list
     152 * \param *pointer      item to be added
     153 * \param *end  end of list
    154154 * \return true - addition succeeded, false - unable to add item to list
    155155 */
    156 template <typename X>  bool add(X *pointer, X *end)
    157 {
    158   if (end != NULL) {
    159     link(pointer, end);
    160   } else {
    161     pointer->previous = NULL;
    162     pointer->next = NULL;
    163   }
    164   return true;
     156template <typename X>   bool add(X *pointer, X *end)
     157{
     158        if (end != NULL) {
     159                link(pointer, end);
     160        } else {
     161                pointer->previous = NULL;
     162                pointer->next = NULL;
     163        }
     164        return true;
    165165};
    166166
    167167/** Finds item in list
    168  * \param *suche  search criteria
    169  * \param *start  begin of list
    170  * \param *end  end of list
     168 * \param *suche        search criteria
     169 * \param *start        begin of list
     170 * \param *end  end of list
    171171 * \return X - if found, NULL - if not found
    172172 */
    173173template <typename X, typename Y> X * find(Y *suche, X *start, X *end)
    174174{
    175   X *walker = start;
    176   while (walker->next != end) { // go through list
    177     walker = walker->next; // step onward beforehand
    178     if (*walker->sort == *suche) return (walker);
    179   }
    180   return NULL;
     175        X *walker = start;
     176        while (walker->next != end) { // go through list
     177                walker = walker->next; // step onward beforehand
     178                if (*walker->sort == *suche) return (walker);
     179        }
     180        return NULL;
    181181};
    182182
     
    187187template <typename X> void removewithoutcheck(X *walker)
    188188{
    189   if (walker != NULL) {
    190     unlink(walker);
    191     delete(walker);
    192     walker = NULL;
    193   }
     189        if (walker != NULL) {
     190                unlink(walker);
     191                delete(walker);
     192                walker = NULL;
     193        }
    194194};
    195195
    196196/** Removes an item from the list, checks if exists.
    197197 * Checks beforehand if atom is really within molecule list.
    198  * \param *pointer  item to be removed
    199  * \param *start  begin of list
    200  * \param *end  end of list
     198 * \param *pointer      item to be removed
     199 * \param *start        begin of list
     200 * \param *end  end of list
    201201 * \return true - removing succeeded, false - given item not found in list
    202202 */
    203203template <typename X> bool remove(X *pointer, X *start, X *end)
    204204{
    205   X *walker = find (pointer->sort, start, end);
    206 /*  while (walker->next != pointer) { // search through list
    207     walker = walker->next;
    208     if (walker == end) return false;  // item not found in list
    209   }*/
    210   // atom found, now unlink
    211   if (walker != NULL)
    212     removewithoutcheck(walker);
    213   else
    214     return false;
    215   return true;
     205        X *walker = find (pointer->sort, start, end);
     206/*      while (walker->next != pointer) { // search through list
     207                walker = walker->next;
     208                if (walker == end) return false;        // item not found in list
     209        }*/
     210        // atom found, now unlink
     211        if (walker != NULL)
     212                removewithoutcheck(walker);
     213        else
     214                return false;
     215        return true;
    216216};
    217217
     
    223223template <typename X> bool cleanup(X *start, X *end)
    224224{
    225   X *pointer = start->next;
    226   X *walker;
    227   while (pointer != end) { // go through list
    228     walker = pointer; // mark current
    229     pointer = pointer->next; // step onward beforehand
    230     // remove walker
    231     unlink(walker);
    232     delete(walker);
    233     walker = NULL;
    234   }
    235   return true;
     225        X *pointer = start->next;
     226        X *walker;
     227        while (pointer != end) { // go through list
     228                walker = pointer; // mark current
     229                pointer = pointer->next; // step onward beforehand
     230                // remove walker
     231                unlink(walker);
     232                delete(walker);
     233                walker = NULL;
     234        }
     235        return true;
    236236};
    237237
     
    242242template <typename X> X *GetFirst(X *me)
    243243{
    244   X *Binder = me;
    245   while(Binder->previous != NULL)
    246     Binder = Binder->previous;
    247   return Binder;
    248 }; 
     244        X *Binder = me;
     245        while(Binder->previous != NULL)
     246                Binder = Binder->previous;
     247        return Binder;
     248};
    249249
    250250/** Returns the last marker in a chain list.
     
    254254template <typename X> X *GetLast(X *me)
    255255{
    256   X *Binder = me;
    257   while(Binder->next != NULL)
    258     Binder = Binder->next;
    259   return Binder;
    260 }; 
     256        X *Binder = me;
     257        while(Binder->next != NULL)
     258                Binder = Binder->next;
     259        return Binder;
     260};
    261261
    262262/** Frees a two-dimensional array.
     
    266266template <typename X> void Free2DArray(X **ptr, int dim)
    267267{
    268   int i;
    269   if (ptr != NULL) {
    270     for(i=dim;i--;)
    271       if (ptr[i] != NULL)
    272         free(ptr[i]);
    273     free(ptr);
    274   }
     268        int i;
     269        if (ptr != NULL) {
     270                for(i=dim;i--;)
     271                        if (ptr[i] != NULL)
     272                                free(ptr[i]);
     273                free(ptr);
     274        }
    275275};
    276276
     
    281281class Verbose
    282282{
    283   public:
    284     Verbose(int value) : Verbosity(value) { }
    285 
    286     ostream& print (ostream &ost) const;
    287   private:
    288     int Verbosity;
     283        public:
     284                Verbose(int value) : Verbosity(value) { }
     285
     286                ostream& print (ostream &ost) const;
     287        private:
     288                int Verbosity;
    289289};
    290290
     
    295295class Binary
    296296{
    297   public:
    298     Binary(int value) : BinaryNumber(value) { }
    299 
    300     ostream& print (ostream &ost) const;
    301   private:
    302     int BinaryNumber;
     297        public:
     298                Binary(int value) : BinaryNumber(value) { }
     299
     300                ostream& print (ostream &ost) const;
     301        private:
     302                int BinaryNumber;
    303303};
    304304
  • src/joiner.cpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    22 *
    33 * Takes evaluated fragments (energy and forces) and by reading the factors files determines total energy
    4  * and each force for the whole molecule. 
    5  *   
     4 * and each force for the whole molecule.
     5 *
    66 */
    77
    88//============================ INCLUDES ===========================
    99
    10 #include "datacreator.hpp" 
    11 #include "helpers.hpp" 
    12 #include "parser.hpp" 
    13 #include "periodentafel.hpp" 
     10#include "datacreator.hpp"
     11#include "helpers.hpp"
     12#include "parser.hpp"
     13#include "periodentafel.hpp"
    1414
    1515//============================== MAIN =============================
     
    1717int main(int argc, char **argv)
    1818{
    19   periodentafel *periode = NULL; // and a period table of all elements
    20   EnergyMatrix Energy;
    21   EnergyMatrix Hcorrection;
    22   ForceMatrix Force;
    23   EnergyMatrix EnergyFragments;
    24   EnergyMatrix HcorrectionFragments;
    25   ForceMatrix ForceFragments;
    26   ForceMatrix Shielding;
    27   ForceMatrix ShieldingPAS;
    28   ForceMatrix ShieldingFragments;
    29   ForceMatrix ShieldingPASFragments;
    30   KeySetsContainer KeySet; 
    31   stringstream prefix;
    32   char *dir = NULL;
    33   bool Hcorrected = true;
     19        periodentafel *periode = NULL; // and a period table of all elements
     20        EnergyMatrix Energy;
     21        EnergyMatrix Hcorrection;
     22        ForceMatrix Force;
     23        EnergyMatrix EnergyFragments;
     24        EnergyMatrix HcorrectionFragments;
     25        ForceMatrix ForceFragments;
     26        ForceMatrix Shielding;
     27        ForceMatrix ShieldingPAS;
     28        ForceMatrix ShieldingFragments;
     29        ForceMatrix ShieldingPASFragments;
     30        KeySetsContainer KeySet;
     31        stringstream prefix;
     32        char *dir = NULL;
     33        bool Hcorrected = true;
    3434
    35   cout << "Joiner" << endl;
    36   cout << "======" << endl;
    37  
    38   // Get the command line options
    39   if (argc < 3) {
    40     cout << "Usage: " << argv[0] << " <inputdir> <prefix> [elementsdb]" << endl;
    41     cout << "<inputdir>\ttherein the output of a molecuilder fragmentation is expected, each fragment with a subdir containing an energy.all and a forces.all file." << endl;
    42     cout << "<prefix>\tprefix of energy and forces file." << endl;
    43     cout << "[elementsdb]\tpath to elements database, needed for shieldings." << endl;
    44     return 1;
    45   } else {
    46     dir = (char *) Malloc(sizeof(char)*(strlen(argv[2])+2), "main: *dir");
    47     strcpy(dir, "/");
    48     strcat(dir, argv[2]);
    49   }
    50   if (argc > 3) {
    51     periode = new periodentafel;
    52     periode->LoadPeriodentafel(argv[3]);
    53   }
    54  
    55   // Test the given directory
    56   if (!TestParams(argc, argv))
    57     return 1;
    58  
    59   // +++++++++++++++++ PARSING +++++++++++++++++++++++++++++++
    60  
    61   // ------------- Parse through all Fragment subdirs --------
    62   if (!Energy.ParseFragmentMatrix(argv[1], dir, EnergySuffix, 0,0)) return 1;
    63   Hcorrected = Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX, 0,0);
    64   if (!Force.ParseFragmentMatrix(argv[1], dir, ForcesSuffix, 0,0)) return 1;
    65   if (periode != NULL) { // also look for PAS values
    66     if (!Shielding.ParseFragmentMatrix(argv[1], dir, ShieldingSuffix, 1, 0)) return 1;
    67     if (!ShieldingPAS.ParseFragmentMatrix(argv[1], dir, ShieldingPASSuffix, 1, 0)) return 1;
    68   }
     35        cout << "Joiner" << endl;
     36        cout << "======" << endl;
    6937
    70   // ---------- Parse the TE Factors into an array -----------------
    71   if (!Energy.ParseIndices()) return 1;
    72   if (Hcorrected) Hcorrection.ParseIndices();
    73  
    74   // ---------- Parse the Force indices into an array ---------------
    75   if (!Force.ParseIndices(argv[1])) return 1;
     38        // Get the command line options
     39        if (argc < 3) {
     40                cout << "Usage: " << argv[0] << " <inputdir> <prefix> [elementsdb]" << endl;
     41                cout << "<inputdir>\ttherein the output of a molecuilder fragmentation is expected, each fragment with a subdir containing an energy.all and a forces.all file." << endl;
     42                cout << "<prefix>\tprefix of energy and forces file." << endl;
     43                cout << "[elementsdb]\tpath to elements database, needed for shieldings." << endl;
     44                return 1;
     45        } else {
     46                dir = (char *) Malloc(sizeof(char)*(strlen(argv[2])+2), "main: *dir");
     47                strcpy(dir, "/");
     48                strcat(dir, argv[2]);
     49        }
     50        if (argc > 3) {
     51                periode = new periodentafel;
     52                periode->LoadPeriodentafel(argv[3]);
     53        }
    7654
    77   // ---------- Parse the shielding indices into an array ---------------
    78   if (periode != NULL) { // also look for PAS values
    79     if(!Shielding.ParseIndices(argv[1])) return 1;
    80     if(!ShieldingPAS.ParseIndices(argv[1])) return 1;
    81   }
     55        // Test the given directory
     56        if (!TestParams(argc, argv))
     57                return 1;
    8258
    83   // ---------- Parse the KeySets into an array ---------------
    84   if (!KeySet.ParseKeySets(argv[1], Force.RowCounter, Force.MatrixCounter)) return 1;
     59        // +++++++++++++++++ PARSING +++++++++++++++++++++++++++++++
    8560
    86   if (!KeySet.ParseManyBodyTerms()) return 1;
    87   if (!EnergyFragments.AllocateMatrix(Energy.Header, Energy.MatrixCounter, Energy.RowCounter, Energy.ColumnCounter)) return 1;
    88   if (Hcorrected)  HcorrectionFragments.AllocateMatrix(Hcorrection.Header, Hcorrection.MatrixCounter, Hcorrection.RowCounter, Hcorrection.ColumnCounter);
    89   if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return 1;
    90   if (periode != NULL) { // also look for PAS values
    91     if (!ShieldingFragments.AllocateMatrix(Shielding.Header, Shielding.MatrixCounter, Shielding.RowCounter, Shielding.ColumnCounter)) return 1;
    92     if (!ShieldingPASFragments.AllocateMatrix(ShieldingPAS.Header, ShieldingPAS.MatrixCounter, ShieldingPAS.RowCounter, ShieldingPAS.ColumnCounter)) return 1;
    93   }
    94  
    95   // ----------- Resetting last matrices (where full QM values are stored right now)
    96   if(!Energy.SetLastMatrix(0., 0)) return 1;
    97   if(!Force.SetLastMatrix(0., 2)) return 1;
    98   if (periode != NULL) { // also look for PAS values
    99     if(!Shielding.SetLastMatrix(0., 2)) return 1;
    100     if(!ShieldingPAS.SetLastMatrix(0., 2)) return 1;
    101   }
     61        // ------------- Parse through all Fragment subdirs --------
     62        if (!Energy.ParseFragmentMatrix(argv[1], dir, EnergySuffix, 0,0)) return 1;
     63        Hcorrected = Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX, 0,0);
     64        if (!Force.ParseFragmentMatrix(argv[1], dir, ForcesSuffix, 0,0)) return 1;
     65        if (periode != NULL) { // also look for PAS values
     66                if (!Shielding.ParseFragmentMatrix(argv[1], dir, ShieldingSuffix, 1, 0)) return 1;
     67                if (!ShieldingPAS.ParseFragmentMatrix(argv[1], dir, ShieldingPASSuffix, 1, 0)) return 1;
     68        }
    10269
    103   // +++++++++++++++++ SUMMING +++++++++++++++++++++++++++++++
     70        // ---------- Parse the TE Factors into an array -----------------
     71        if (!Energy.ParseIndices()) return 1;
     72        if (Hcorrected) Hcorrection.ParseIndices();
    10473
    105   // --------- sum up and write for each order----------------
    106   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
    107     // --------- sum up energy --------------------
    108     cout << "Summing energy of order " << BondOrder+1 << " ..." << endl;
    109     if (!EnergyFragments.SumSubManyBodyTerms(Energy, KeySet, BondOrder)) return 1;
    110     if (Hcorrected) {
    111       HcorrectionFragments.SumSubManyBodyTerms(Hcorrection, KeySet, BondOrder);
    112       if (!Energy.SumSubEnergy(EnergyFragments, &HcorrectionFragments, KeySet, BondOrder, 1.)) return 1;
    113       if (Hcorrected) Hcorrection.SumSubEnergy(HcorrectionFragments, NULL, KeySet, BondOrder, 1.);
    114     } else
    115       if (!Energy.SumSubEnergy(EnergyFragments, NULL, KeySet, BondOrder, 1.)) return 1;
    116     // --------- sum up Forces --------------------
    117     cout << "Summing forces of order " << BondOrder+1 << " ..." << endl;
    118     if (!ForceFragments.SumSubManyBodyTerms(Force, KeySet, BondOrder)) return 1;
    119     if (!Force.SumSubForces(ForceFragments, KeySet, BondOrder, 1.)) return 1;
    120     if (periode != NULL) { // also look for PAS values
    121       cout << "Summing shieldings of order " << BondOrder+1 << " ..." << endl;
    122       if (!ShieldingFragments.SumSubManyBodyTerms(Shielding, KeySet, BondOrder)) return 1;
    123       if (!Shielding.SumSubForces(ShieldingFragments, KeySet, BondOrder, 1.)) return 1;
    124       if (!ShieldingPASFragments.SumSubManyBodyTerms(ShieldingPAS, KeySet, BondOrder)) return 1;
    125       if (!ShieldingPAS.SumSubForces(ShieldingPASFragments, KeySet, BondOrder, 1.)) return 1;
    126     }
     74        // ---------- Parse the Force indices into an array ---------------
     75        if (!Force.ParseIndices(argv[1])) return 1;
    12776
    128     // --------- write the energy and forces file --------------------
    129     prefix.str(" ");
    130     prefix << dir << OrderSuffix << (BondOrder+1);
    131     cout << "Writing files " << argv[1] << prefix.str() << ". ..." << endl;
    132     // energy
    133     if (!Energy.WriteLastMatrix(argv[1], (prefix.str()).c_str(), EnergySuffix)) return 1;
    134     // forces
    135     if (!Force.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ForcesSuffix)) return 1;
    136     // shieldings
    137     if (periode != NULL) { // also look for PAS values
    138       if (!Shielding.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ShieldingSuffix)) return 1;
    139       if (!ShieldingPAS.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ShieldingPASSuffix)) return 1;
    140     }
    141   }
    142   // fragments
    143   prefix.str(" ");
    144   prefix << dir << EnergyFragmentSuffix;
    145   if (!EnergyFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
    146   if (Hcorrected) {
    147     prefix.str(" ");
    148     prefix << dir << HcorrectionFragmentSuffix;
    149     if (!HcorrectionFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
    150   }
    151   prefix.str(" ");
    152   prefix << dir << ForceFragmentSuffix;
    153   if (!ForceFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
    154   if (!CreateDataFragment(EnergyFragments, KeySet, argv[1], FRAGMENTPREFIX ENERGYPERFRAGMENT, "fragment energy versus the Fragment No", "today", CreateEnergy)) return 1;
    155   if (periode != NULL) { // also look for PAS values
    156     prefix.str(" ");
    157     prefix << dir << ShieldingFragmentSuffix;
    158     if (!ShieldingFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
    159     prefix.str(" ");
    160     prefix << dir << ShieldingPASFragmentSuffix;
    161     if (!ShieldingPASFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
    162   }
     77        // ---------- Parse the shielding indices into an array ---------------
     78        if (periode != NULL) { // also look for PAS values
     79                if(!Shielding.ParseIndices(argv[1])) return 1;
     80                if(!ShieldingPAS.ParseIndices(argv[1])) return 1;
     81        }
    16382
    164   // write last matrices as fragments into central dir (not subdir as above), for analyzer to know index bounds
    165   if (!Energy.WriteLastMatrix(argv[1], dir, EnergyFragmentSuffix)) return 1;
    166   if (Hcorrected) Hcorrection.WriteLastMatrix(argv[1], dir, HcorrectionFragmentSuffix);
    167   if (!Force.WriteLastMatrix(argv[1], dir, ForceFragmentSuffix)) return 1;
    168   if (periode != NULL) { // also look for PAS values
    169     if (!Shielding.WriteLastMatrix(argv[1], dir, ShieldingFragmentSuffix)) return 1;
    170     if (!ShieldingPAS.WriteLastMatrix(argv[1], dir, ShieldingPASFragmentSuffix)) return 1;
    171   }
     83        // ---------- Parse the KeySets into an array ---------------
     84        if (!KeySet.ParseKeySets(argv[1], Force.RowCounter, Force.MatrixCounter)) return 1;
    17285
    173   // exit 
    174   delete(periode);
    175   Free((void **)&dir, "main: *dir");
    176   cout << "done." << endl;
    177   return 0;
     86        if (!KeySet.ParseManyBodyTerms()) return 1;
     87        if (!EnergyFragments.AllocateMatrix(Energy.Header, Energy.MatrixCounter, Energy.RowCounter, Energy.ColumnCounter)) return 1;
     88        if (Hcorrected) HcorrectionFragments.AllocateMatrix(Hcorrection.Header, Hcorrection.MatrixCounter, Hcorrection.RowCounter, Hcorrection.ColumnCounter);
     89        if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return 1;
     90        if (periode != NULL) { // also look for PAS values
     91                if (!ShieldingFragments.AllocateMatrix(Shielding.Header, Shielding.MatrixCounter, Shielding.RowCounter, Shielding.ColumnCounter)) return 1;
     92                if (!ShieldingPASFragments.AllocateMatrix(ShieldingPAS.Header, ShieldingPAS.MatrixCounter, ShieldingPAS.RowCounter, ShieldingPAS.ColumnCounter)) return 1;
     93        }
     94
     95        // ----------- Resetting last matrices (where full QM values are stored right now)
     96        if(!Energy.SetLastMatrix(0., 0)) return 1;
     97        if(!Force.SetLastMatrix(0., 2)) return 1;
     98        if (periode != NULL) { // also look for PAS values
     99                if(!Shielding.SetLastMatrix(0., 2)) return 1;
     100                if(!ShieldingPAS.SetLastMatrix(0., 2)) return 1;
     101        }
     102
     103        // +++++++++++++++++ SUMMING +++++++++++++++++++++++++++++++
     104
     105        // --------- sum up and write for each order----------------
     106        for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     107                // --------- sum up energy --------------------
     108                cout << "Summing energy of order " << BondOrder+1 << " ..." << endl;
     109                if (!EnergyFragments.SumSubManyBodyTerms(Energy, KeySet, BondOrder)) return 1;
     110                if (Hcorrected) {
     111                        HcorrectionFragments.SumSubManyBodyTerms(Hcorrection, KeySet, BondOrder);
     112                        if (!Energy.SumSubEnergy(EnergyFragments, &HcorrectionFragments, KeySet, BondOrder, 1.)) return 1;
     113                        if (Hcorrected) Hcorrection.SumSubEnergy(HcorrectionFragments, NULL, KeySet, BondOrder, 1.);
     114                } else
     115                        if (!Energy.SumSubEnergy(EnergyFragments, NULL, KeySet, BondOrder, 1.)) return 1;
     116                // --------- sum up Forces --------------------
     117                cout << "Summing forces of order " << BondOrder+1 << " ..." << endl;
     118                if (!ForceFragments.SumSubManyBodyTerms(Force, KeySet, BondOrder)) return 1;
     119                if (!Force.SumSubForces(ForceFragments, KeySet, BondOrder, 1.)) return 1;
     120                if (periode != NULL) { // also look for PAS values
     121                        cout << "Summing shieldings of order " << BondOrder+1 << " ..." << endl;
     122                        if (!ShieldingFragments.SumSubManyBodyTerms(Shielding, KeySet, BondOrder)) return 1;
     123                        if (!Shielding.SumSubForces(ShieldingFragments, KeySet, BondOrder, 1.)) return 1;
     124                        if (!ShieldingPASFragments.SumSubManyBodyTerms(ShieldingPAS, KeySet, BondOrder)) return 1;
     125                        if (!ShieldingPAS.SumSubForces(ShieldingPASFragments, KeySet, BondOrder, 1.)) return 1;
     126                }
     127
     128                // --------- write the energy and forces file --------------------
     129                prefix.str(" ");
     130                prefix << dir << OrderSuffix << (BondOrder+1);
     131                cout << "Writing files " << argv[1] << prefix.str() << ". ..." << endl;
     132                // energy
     133                if (!Energy.WriteLastMatrix(argv[1], (prefix.str()).c_str(), EnergySuffix)) return 1;
     134                // forces
     135                if (!Force.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ForcesSuffix)) return 1;
     136                // shieldings
     137                if (periode != NULL) { // also look for PAS values
     138                        if (!Shielding.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ShieldingSuffix)) return 1;
     139                        if (!ShieldingPAS.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ShieldingPASSuffix)) return 1;
     140                }
     141        }
     142        // fragments
     143        prefix.str(" ");
     144        prefix << dir << EnergyFragmentSuffix;
     145        if (!EnergyFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
     146        if (Hcorrected) {
     147                prefix.str(" ");
     148                prefix << dir << HcorrectionFragmentSuffix;
     149                if (!HcorrectionFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
     150        }
     151        prefix.str(" ");
     152        prefix << dir << ForceFragmentSuffix;
     153        if (!ForceFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
     154        if (!CreateDataFragment(EnergyFragments, KeySet, argv[1], FRAGMENTPREFIX ENERGYPERFRAGMENT, "fragment energy versus the Fragment No", "today", CreateEnergy)) return 1;
     155        if (periode != NULL) { // also look for PAS values
     156                prefix.str(" ");
     157                prefix << dir << ShieldingFragmentSuffix;
     158                if (!ShieldingFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
     159                prefix.str(" ");
     160                prefix << dir << ShieldingPASFragmentSuffix;
     161                if (!ShieldingPASFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
     162        }
     163
     164        // write last matrices as fragments into central dir (not subdir as above), for analyzer to know index bounds
     165        if (!Energy.WriteLastMatrix(argv[1], dir, EnergyFragmentSuffix)) return 1;
     166        if (Hcorrected) Hcorrection.WriteLastMatrix(argv[1], dir, HcorrectionFragmentSuffix);
     167        if (!Force.WriteLastMatrix(argv[1], dir, ForceFragmentSuffix)) return 1;
     168        if (periode != NULL) { // also look for PAS values
     169                if (!Shielding.WriteLastMatrix(argv[1], dir, ShieldingFragmentSuffix)) return 1;
     170                if (!ShieldingPAS.WriteLastMatrix(argv[1], dir, ShieldingPASFragmentSuffix)) return 1;
     171        }
     172
     173        // exit
     174        delete(periode);
     175        Free((void **)&dir, "main: *dir");
     176        cout << "done." << endl;
     177        return 0;
    178178};
    179179
  • src/linkedcell.cpp

    r124df1 r6ac7ee  
    66LinkedCell::LinkedCell()
    77{
    8   LC = NULL;
    9   for(int i=0;i<NDIM;i++)
    10     N[i] = 0;
    11   index = -1;
    12   RADIUS = 0.;
    13   max.Zero();
    14   min.Zero();
     8        LC = NULL;
     9        for(int i=0;i<NDIM;i++)
     10                N[i] = 0;
     11        index = -1;
     12        RADIUS = 0.;
     13        max.Zero();
     14        min.Zero();
    1515};
    1616
     
    2121LinkedCell::LinkedCell(molecule *mol, double radius)
    2222{
    23   atom *Walker = NULL;
     23        atom *Walker = NULL;
    2424
    25   RADIUS = radius;
    26   LC = NULL;
    27   for(int i=0;i<NDIM;i++)
    28     N[i] = 0;
    29   index = -1;
    30   max.Zero();
    31   min.Zero();
    32   cout << Verbose(1) << "Begin of LinkedCell" << endl;
    33   if (mol->start->next == mol->end) {
    34     cerr << "ERROR: molecule contains no atoms!" << endl;
    35     return;
    36   }
    37   // 1. find max and min per axis of atoms
    38   Walker = mol->start->next;
    39   for (int i=0;i<NDIM;i++) {
    40     max.x[i] = Walker->x.x[i];
    41     min.x[i] = Walker->x.x[i];
    42   }
    43   while (Walker != mol->end) {
    44     for (int i=0;i<NDIM;i++) {
    45       if (max.x[i] < Walker->x.x[i])
    46         max.x[i] = Walker->x.x[i];
    47       if (min.x[i] > Walker->x.x[i])
    48         min.x[i] = Walker->x.x[i];
    49     }
    50     Walker = Walker->next;
    51   }
    52   cout << Verbose(2) << "Bounding box is " << min << " and " << max << "." << endl;
    53  
    54   // 2. find then umber of cells per axis
    55   for (int i=0;i<NDIM;i++) {
    56     N[i] = (int)floor((max.x[i] - min.x[i])/RADIUS)+1;
    57   }
    58   cout << Verbose(2) << "Number of cells per axis are " << N[0] << ", " << N[1] << " and " << N[2] << "." << endl;
    59  
    60   // 3. allocate the lists 
    61   cout << Verbose(2) << "Allocating cells ... " << endl;
    62   if (LC != NULL) {
    63     cout << Verbose(1) << "ERROR: Linked Cell list is already allocated, I do nothing." << endl;
    64     return;
    65   }
    66   LC = new LinkedAtoms[N[0]*N[1]*N[2]];
    67   for (index=0;index<N[0]*N[1]*N[2];index++) {
    68     LC [index].clear();
    69   }
    70  
    71   // 4. put each atom into its respective cell
    72   Walker = mol->start;
    73   while (Walker->next != mol->end) {
    74     Walker = Walker->next;
    75     for (int i=0;i<NDIM;i++) {
    76       n[i] = (int)floor((Walker->x.x[i] - min.x[i])/RADIUS);
    77     }
    78     index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2];
    79     LC[index].push_back(Walker);
    80     cout << Verbose(2) << *Walker << " goes into cell " << n[0] << ", " << n[1] << ", " << n[2] << " with No. " << index << "." << endl;
    81   }
    82   cout << Verbose(1) << "End of LinkedCell" << endl;
     25        RADIUS = radius;
     26        LC = NULL;
     27        for(int i=0;i<NDIM;i++)
     28                N[i] = 0;
     29        index = -1;
     30        max.Zero();
     31        min.Zero();
     32        cout << Verbose(1) << "Begin of LinkedCell" << endl;
     33        if (mol->start->next == mol->end) {
     34                cerr << "ERROR: molecule contains no atoms!" << endl;
     35                return;
     36        }
     37        // 1. find max and min per axis of atoms
     38        Walker = mol->start->next;
     39        for (int i=0;i<NDIM;i++) {
     40                max.x[i] = Walker->x.x[i];
     41                min.x[i] = Walker->x.x[i];
     42        }
     43        while (Walker != mol->end) {
     44                for (int i=0;i<NDIM;i++) {
     45                        if (max.x[i] < Walker->x.x[i])
     46                                max.x[i] = Walker->x.x[i];
     47                        if (min.x[i] > Walker->x.x[i])
     48                                min.x[i] = Walker->x.x[i];
     49                }
     50                Walker = Walker->next;
     51        }
     52        cout << Verbose(2) << "Bounding box is " << min << " and " << max << "." << endl;
     53
     54        // 2. find then umber of cells per axis
     55        for (int i=0;i<NDIM;i++) {
     56                N[i] = (int)floor((max.x[i] - min.x[i])/RADIUS)+1;
     57        }
     58        cout << Verbose(2) << "Number of cells per axis are " << N[0] << ", " << N[1] << " and " << N[2] << "." << endl;
     59
     60        // 3. allocate the lists
     61        cout << Verbose(2) << "Allocating cells ... " << endl;
     62        if (LC != NULL) {
     63                cout << Verbose(1) << "ERROR: Linked Cell list is already allocated, I do nothing." << endl;
     64                return;
     65        }
     66        LC = new LinkedAtoms[N[0]*N[1]*N[2]];
     67        for (index=0;index<N[0]*N[1]*N[2];index++) {
     68                LC [index].clear();
     69        }
     70
     71        // 4. put each atom into its respective cell
     72        Walker = mol->start;
     73        while (Walker->next != mol->end) {
     74                Walker = Walker->next;
     75                for (int i=0;i<NDIM;i++) {
     76                        n[i] = (int)floor((Walker->x.x[i] - min.x[i])/RADIUS);
     77                }
     78                index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2];
     79                LC[index].push_back(Walker);
     80                cout << Verbose(2) << *Walker << " goes into cell " << n[0] << ", " << n[1] << ", " << n[2] << " with No. " << index << "." << endl;
     81        }
     82        cout << Verbose(1) << "End of LinkedCell" << endl;
    8383};
    8484
     
    8787LinkedCell::~LinkedCell()
    8888{
    89   if (LC != NULL)
    90     for (index=0;index<N[0]*N[1]*N[2];index++)
    91       LC[index].clear();
    92   delete[](LC);
    93   for(int i=0;i<NDIM;i++)
    94     N[i] = 0;
    95   index = -1;
    96   max.Zero();
    97   min.Zero();
     89        if (LC != NULL)
     90        for (index=0;index<N[0]*N[1]*N[2];index++)
     91                LC[index].clear();
     92        delete[](LC);
     93        for(int i=0;i<NDIM;i++)
     94                N[i] = 0;
     95        index = -1;
     96        max.Zero();
     97        min.Zero();
    9898};
    9999
     
    103103bool LinkedCell::CheckBounds()
    104104{
    105   bool status = true;
    106   for(int i=0;i<NDIM;i++)
    107     status = status && ((n[i] >=0) && (n[i] < N[i]));
    108   if (!status)
    109     cerr << "ERROR: indices are out of bounds!" << endl;
    110   return status;
     105        bool status = true;
     106        for(int i=0;i<NDIM;i++)
     107                status = status && ((n[i] >=0) && (n[i] < N[i]));
     108        if (!status)
     109        cerr << "ERROR: indices are out of bounds!" << endl;
     110        return status;
    111111};
    112112
     
    117117LinkedAtoms* LinkedCell::GetCurrentCell()
    118118{
    119   if (CheckBounds()) {
    120     index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2];
    121     return (&(LC[index]));
    122   } else {
    123     return NULL;
    124   }
     119        if (CheckBounds()) {
     120                index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2];
     121                return (&(LC[index]));
     122        } else {
     123                return NULL;
     124        }
    125125};
    126126
     
    131131bool LinkedCell::SetIndexToAtom(atom *Walker)
    132132{
    133   bool status = false;
    134   for (int i=0;i<NDIM;i++) {
    135     n[i] = (int)floor((Walker->x.x[i] - min.x[i])/RADIUS);
    136   }
    137   index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2];
    138   if (CheckBounds()) {
    139     for (LinkedAtoms::iterator Runner = LC[index].begin(); Runner != LC[index].end(); Runner++)
    140       status = status || ((*Runner) == Walker);
    141     return status;
    142   } else {
    143     cerr << Verbose(1) << "ERROR: Atom "<< *Walker << " at " << Walker->x << " is out of bounds." << endl;
    144     return false;
    145   }
     133        bool status = false;
     134        for (int i=0;i<NDIM;i++) {
     135                n[i] = (int)floor((Walker->x.x[i] - min.x[i])/RADIUS);
     136        }
     137        index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2];
     138        if (CheckBounds()) {
     139                for (LinkedAtoms::iterator Runner = LC[index].begin(); Runner != LC[index].end(); Runner++)
     140                        status = status || ((*Runner) == Walker);
     141                return status;
     142        } else {
     143                cerr << Verbose(1) << "ERROR: Atom "<< *Walker << " at " << Walker->x << " is out of bounds." << endl;
     144                return false;
     145        }
    146146};
    147147
     
    152152bool LinkedCell::SetIndexToVector(Vector *x)
    153153{
    154   bool status = true;
    155   for (int i=0;i<NDIM;i++) {
    156     n[i] = (int)floor((x->x[i] - min.x[i])/RADIUS);
    157     if (max.x[i] < x->x[i])
    158       status = false;
    159     if (min.x[i] > x->x[i])
    160       status = false;
    161   }
    162   return status;
     154        bool status = true;
     155        for (int i=0;i<NDIM;i++) {
     156                n[i] = (int)floor((x->x[i] - min.x[i])/RADIUS);
     157                if (max.x[i] < x->x[i])
     158                        status = false;
     159                if (min.x[i] > x->x[i])
     160                        status = false;
     161        }
     162        return status;
    163163};
     164
  • src/linkedcell.hpp

    r124df1 r6ac7ee  
    99#include "molecules.hpp"
    1010
     11#define LinkedAtoms list <atom *>
     12
    1113class LinkedCell{
    12   public:
    13     Vector max;       // upper boundary
    14     Vector min;       // lower boundary
    15     LinkedAtoms *LC;  // linked cell list
    16     double RADIUS;    // cell edge length
    17     int N[NDIM];      // number of cells per axis
    18     int n[NDIM];      // temporary variable for current cell per axis
    19     int index;        // temporary index variable , access by index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2];
    20    
    21     LinkedCell();
    22     LinkedCell(molecule *mol, double RADIUS);
    23     ~LinkedCell();
    24     LinkedAtoms* GetCurrentCell();
    25     bool SetIndexToAtom(atom *Walker);
    26     bool SetIndexToVector(Vector *x);
    27     bool CheckBounds();
     14        public:
     15                Vector max;                      // upper boundary
     16                Vector min;                      // lower boundary
     17                LinkedAtoms *LC;        // linked cell list
     18                double RADIUS;          // cell edge length
     19                int N[NDIM];                    // number of cells per axis
     20                int n[NDIM];                    // temporary variable for current cell per axis
     21                int index;                              // temporary index variable , access by index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2];
     22
     23                LinkedCell();
     24                LinkedCell(molecule *mol, double RADIUS);
     25                ~LinkedCell();
     26                LinkedAtoms* GetCurrentCell();
     27                bool SetIndexToAtom(atom *Walker);
     28                bool SetIndexToVector(Vector *x);
     29                bool CheckBounds();
     30
     31                // not implemented yet
     32                bool AddAtom(atom *Walker);
     33                bool DeleteAtom(atom *Walker);
     34                bool MoveAtom(atom *Walker);
    2835};
    2936
  • src/moleculelist.cpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    2121MoleculeListClass::MoleculeListClass(int NumMolecules, int NumAtoms)
    2222{
    23   ListOfMolecules = (molecule **) Malloc(sizeof(molecule *)*NumMolecules, "MoleculeListClass:MoleculeListClass: **ListOfMolecules");
    24   for (int i=NumMolecules;i--;)
    25     ListOfMolecules[i] = NULL;
    26   NumberOfMolecules = NumMolecules;
    27   NumberOfTopAtoms = NumAtoms;
     23        ListOfMolecules = (molecule **) Malloc(sizeof(molecule *)*NumMolecules, "MoleculeListClass:MoleculeListClass: **ListOfMolecules");
     24        for (int i=NumMolecules;i--;)
     25                ListOfMolecules[i] = NULL;
     26        NumberOfMolecules = NumMolecules;
     27        NumberOfTopAtoms = NumAtoms;
    2828};
    2929
     
    3333MoleculeListClass::~MoleculeListClass()
    3434{
    35   cout << Verbose(3) << this << ": Freeing ListOfMolcules." << endl;
    36   for (int i=NumberOfMolecules;i--;) {
    37     if (ListOfMolecules[i] != NULL) { // if NULL don't free
    38       cout << Verbose(4) << "ListOfMolecules: Freeing " << ListOfMolecules[i] << "." << endl;
    39       delete(ListOfMolecules[i]);
    40       ListOfMolecules[i] = NULL;
    41     }
    42   }
    43   cout << Verbose(4) << "Freeing ListOfMolecules." << endl;
    44   Free((void **)&ListOfMolecules, "MoleculeListClass:MoleculeListClass: **ListOfMolecules");
     35        cout << Verbose(3) << this << ": Freeing ListOfMolcules." << endl;
     36        for (int i=NumberOfMolecules;i--;) {
     37                if (ListOfMolecules[i] != NULL) { // if NULL don't free
     38                        cout << Verbose(4) << "ListOfMolecules: Freeing " << ListOfMolecules[i] << "." << endl;
     39                        delete(ListOfMolecules[i]);
     40                        ListOfMolecules[i] = NULL;
     41                }
     42        }
     43        cout << Verbose(4) << "Freeing ListOfMolecules." << endl;
     44        Free((void **)&ListOfMolecules, "MoleculeListClass:MoleculeListClass: **ListOfMolecules");
    4545};
    4646
     
    5252int MolCompare(const void *a, const void *b)
    5353{
    54   int *aList = NULL, *bList = NULL;
    55   int Count, Counter, aCounter, bCounter;
    56   int flag;
    57   atom *aWalker = NULL;
    58   atom *bWalker = NULL;
    59  
    60   // sort each atom list and put the numbers into a list, then go through
    61   //cout << "Comparing fragment no. " << *(molecule **)a << " to " << *(molecule **)b << "." << endl;
    62   if ( (**(molecule **)a).AtomCount < (**(molecule **)b).AtomCount ) {
    63     return -1;
    64   } else { if ((**(molecule **)a).AtomCount > (**(molecule **)b).AtomCount)
    65     return +1;
    66     else {
    67       Count = (**(molecule **)a).AtomCount;
    68       aList = new int[Count];
    69       bList = new int[Count];
    70  
    71       // fill the lists
    72       aWalker = (**(molecule **)a).start;
    73       bWalker = (**(molecule **)b).start;
    74       Counter = 0;
    75       aCounter = 0;
    76       bCounter = 0;
    77       while ((aWalker->next != (**(molecule **)a).end) && (bWalker->next != (**(molecule **)b).end)) {
    78         aWalker = aWalker->next;
    79         bWalker = bWalker->next;
    80         if (aWalker->GetTrueFather() == NULL)
    81           aList[Counter] = Count + (aCounter++);
    82         else
    83           aList[Counter] = aWalker->GetTrueFather()->nr;
    84         if (bWalker->GetTrueFather() == NULL)
    85           bList[Counter] = Count + (bCounter++);
    86         else
    87           bList[Counter] = bWalker->GetTrueFather()->nr;
    88         Counter++;
    89       }
    90       // check if AtomCount was for real
    91       flag = 0;
    92       if ((aWalker->next == (**(molecule **)a).end) && (bWalker->next != (**(molecule **)b).end)) {
    93         flag = -1;
    94       } else {
    95         if ((aWalker->next != (**(molecule **)a).end) && (bWalker->next == (**(molecule **)b).end))
    96           flag = 1;
    97       }
    98       if (flag == 0) {
    99         // sort the lists
    100         gsl_heapsort(aList,Count, sizeof(int), CompareDoubles);
    101         gsl_heapsort(bList,Count, sizeof(int), CompareDoubles);
    102         // compare the lists
    103        
    104         flag = 0;
    105         for(int i=0;i<Count;i++) {
    106           if (aList[i] < bList[i]) {
    107             flag = -1;
    108           } else {
    109             if (aList[i] > bList[i])
    110               flag = 1;
    111           }
    112           if (flag != 0)
    113             break;
    114         }
    115       }
    116       delete[](aList);
    117       delete[](bList);
    118       return flag;
    119     }
    120   }
    121   return  -1;
     54        int *aList = NULL, *bList = NULL;
     55        int Count, Counter, aCounter, bCounter;
     56        int flag;
     57        atom *aWalker = NULL;
     58        atom *bWalker = NULL;
     59       
     60        // sort each atom list and put the numbers into a list, then go through
     61        //cout << "Comparing fragment no. " << *(molecule **)a << " to " << *(molecule **)b << "." << endl;
     62        if ( (**(molecule **)a).AtomCount < (**(molecule **)b).AtomCount ) {
     63                return -1;
     64        } else { if ((**(molecule **)a).AtomCount > (**(molecule **)b).AtomCount)
     65                return +1;
     66                else {
     67                        Count = (**(molecule **)a).AtomCount;
     68                        aList = new int[Count];
     69                        bList = new int[Count];
     70       
     71                        // fill the lists
     72                        aWalker = (**(molecule **)a).start;
     73                        bWalker = (**(molecule **)b).start;
     74                        Counter = 0;
     75                        aCounter = 0;
     76                        bCounter = 0;
     77                        while ((aWalker->next != (**(molecule **)a).end) && (bWalker->next != (**(molecule **)b).end)) {
     78                                aWalker = aWalker->next;
     79                                bWalker = bWalker->next;
     80                                if (aWalker->GetTrueFather() == NULL)
     81                                        aList[Counter] = Count + (aCounter++);
     82                                else
     83                                        aList[Counter] = aWalker->GetTrueFather()->nr;
     84                                if (bWalker->GetTrueFather() == NULL)
     85                                        bList[Counter] = Count + (bCounter++);
     86                                else
     87                                        bList[Counter] = bWalker->GetTrueFather()->nr;
     88                                Counter++;
     89                        }
     90                        // check if AtomCount was for real
     91                        flag = 0;
     92                        if ((aWalker->next == (**(molecule **)a).end) && (bWalker->next != (**(molecule **)b).end)) {
     93                                flag = -1;
     94                        } else {
     95                                if ((aWalker->next != (**(molecule **)a).end) && (bWalker->next == (**(molecule **)b).end))
     96                                        flag = 1;
     97                        }
     98                        if (flag == 0) {
     99                                // sort the lists
     100                                gsl_heapsort(aList,Count, sizeof(int), CompareDoubles);
     101                                gsl_heapsort(bList,Count, sizeof(int), CompareDoubles);
     102                                // compare the lists
     103                               
     104                                flag = 0;
     105                                for(int i=0;i<Count;i++) {
     106                                        if (aList[i] < bList[i]) {
     107                                                flag = -1;
     108                                        } else {
     109                                                if (aList[i] > bList[i])
     110                                                        flag = 1;
     111                                        }
     112                                        if (flag != 0)
     113                                                break;
     114                                }
     115                        }
     116                        delete[](aList);
     117                        delete[](bList);
     118                        return flag;
     119                }
     120        }
     121        return  -1;
    122122};
    123123
     
    127127void MoleculeListClass::Output(ofstream *out)
    128128{
    129   *out<< Verbose(1) << "MoleculeList: ";
    130   for (int i=0;i<NumberOfMolecules;i++)
    131     *out << ListOfMolecules[i] << "\t";
    132   *out << endl;
     129        *out<< Verbose(1) << "MoleculeList: ";
     130        for (int i=0;i<NumberOfMolecules;i++)
     131                *out << ListOfMolecules[i] << "\t";
     132        *out << endl;
    133133};
    134134
     
    142142bool MoleculeListClass::AddHydrogenCorrection(ofstream *out, char *path)
    143143{
    144   atom *Walker = NULL;
    145   atom *Runner = NULL;
    146   double ***FitConstant = NULL, **correction = NULL;
    147   int a,b;
    148   ofstream output;
    149   ifstream input;
    150   string line;
    151   stringstream zeile;
    152   double distance;
    153   char ParsedLine[1023];
    154   double tmp;
    155   char *FragmentNumber = NULL;
    156 
    157   cout << Verbose(1) << "Saving hydrogen saturation correction ... ";
    158   // 0. parse in fit constant files that should have the same dimension as the final energy files
    159   // 0a. find dimension of matrices with constants
    160   line = path;
    161   line.append("/");
    162   line += FRAGMENTPREFIX;
    163   line += "1";
    164   line += FITCONSTANTSUFFIX;
    165   input.open(line.c_str());
    166   if (input == NULL) {
    167     cerr << endl << "Unable to open " << line << ", is the directory correct?" << endl;
    168     return false;
    169   }
    170   a=0;
    171   b=-1; // we overcount by one
    172   while (!input.eof()) {
    173     input.getline(ParsedLine, 1023);
    174     zeile.str(ParsedLine);
    175     int i=0;
    176     while (!zeile.eof()) {
    177       zeile >> distance;
    178       i++;
    179     }
    180     if (i > a)
    181       a = i;
    182     b++;
    183   }
    184   cout << "I recognized " << a << " columns and " << b << " rows, ";
    185   input.close();
    186  
    187   // 0b. allocate memory for constants
    188   FitConstant = (double ***) Malloc(sizeof(double **)*3, "MoleculeListClass::AddHydrogenCorrection: ***FitConstant");
    189   for (int k=0;k<3;k++) {
    190     FitConstant[k] = (double **) Malloc(sizeof(double *)*a, "MoleculeListClass::AddHydrogenCorrection: **FitConstant[]");
    191     for (int i=a;i--;) {
    192       FitConstant[k][i] = (double *) Malloc(sizeof(double)*b, "MoleculeListClass::AddHydrogenCorrection: *FitConstant[][]");
    193     }
    194   }
    195   // 0c. parse in constants
    196   for (int i=0;i<3;i++) {
    197     line = path;
    198     line.append("/");
    199     line += FRAGMENTPREFIX;
    200     sprintf(ParsedLine, "%d", i+1);
    201     line += ParsedLine;
    202     line += FITCONSTANTSUFFIX;
    203     input.open(line.c_str());
    204     if (input == NULL) {
    205       cerr << endl << "Unable to open " << line << ", is the directory correct?" << endl;
    206       return false;
    207     }
    208     int k = 0,l;
    209     while ((!input.eof()) && (k < b)) {
    210       input.getline(ParsedLine, 1023);
    211       //cout << "Current Line: " << ParsedLine << endl;
    212       zeile.str(ParsedLine);
    213       zeile.clear();
    214       l = 0;
    215       while ((!zeile.eof()) && (l < a)) {
    216         zeile >> FitConstant[i][l][k];
    217         //cout << FitConstant[i][l][k] << "\t";
    218         l++;
    219       }
    220       //cout << endl;
    221       k++;
    222     }
    223     input.close();
    224   }
    225   for(int k=0;k<3;k++) {
    226     cout << "Constants " << k << ":" << endl;
    227     for (int j=0;j<b;j++) {
    228       for (int i=0;i<a;i++) {
    229         cout << FitConstant[k][i][j] << "\t";
    230       }
    231       cout << endl;
    232     }
    233     cout << endl;
    234   }
    235  
    236   // 0d. allocate final correction matrix
    237   correction = (double **) Malloc(sizeof(double *)*a, "MoleculeListClass::AddHydrogenCorrection: **correction");
    238   for (int i=a;i--;)
    239     correction[i] = (double *) Malloc(sizeof(double)*b, "MoleculeListClass::AddHydrogenCorrection: *correction[]");
    240        
    241   // 1a. go through every molecule in the list
    242   for(int i=NumberOfMolecules;i--;) {
    243     // 1b. zero final correction matrix
    244     for (int k=a;k--;)
    245       for (int j=b;j--;)
    246         correction[k][j] = 0.;
    247     // 2. take every hydrogen that is a saturated one
    248     Walker = ListOfMolecules[i]->start;
    249     while (Walker->next != ListOfMolecules[i]->end) {
    250       Walker = Walker->next;
    251       //cout << Verbose(1) << "Walker: " << *Walker << " with first bond " << *ListOfMolecules[i]->ListOfBondsPerAtom[Walker->nr][0] << "." << endl;
    252       if ((Walker->type->Z == 1) && ((Walker->father == NULL) || (Walker->father->type->Z != 1))) { // if it's a hydrogen
    253         Runner = ListOfMolecules[i]->start;
    254         while (Runner->next != ListOfMolecules[i]->end) {
    255           Runner = Runner->next;
    256           //cout << Verbose(2) << "Runner: " << *Runner << " with first bond " << *ListOfMolecules[i]->ListOfBondsPerAtom[Runner->nr][0] << "." << endl;
    257           // 3. take every other hydrogen that is the not the first and not bound to same bonding partner
    258           if ((Runner->type->Z == 1) && (Runner->nr > Walker->nr) && (ListOfMolecules[i]->ListOfBondsPerAtom[Runner->nr][0]->GetOtherAtom(Runner) != ListOfMolecules[i]->ListOfBondsPerAtom[Walker->nr][0]->GetOtherAtom(Walker))) {  // (hydrogens have only one bonding partner!)
    259             // 4. evaluate the morse potential for each matrix component and add up
    260             distance = sqrt(Runner->x.Distance(&Walker->x));
    261             //cout << "Fragment " << i << ": " << *Runner << "<= " << distance << "=>" << *Walker << ":" << endl;
    262             for(int k=0;k<a;k++) {
    263               for (int j=0;j<b;j++) {
    264                 switch(k) {
    265                 case 1:
    266                 case 7:
    267                 case 11:
    268                   tmp = pow(FitConstant[0][k][j] * ( 1. - exp(-FitConstant[1][k][j] * (distance - FitConstant[2][k][j]) ) ),2);
    269                   break;
    270                 default:
    271                   tmp = FitConstant[0][k][j] * pow( distance,  FitConstant[1][k][j]) + FitConstant[2][k][j];
    272                 };
    273                 correction[k][j] -= tmp;    // ground state is actually lower (disturbed by additional interaction)
    274                 //cout << tmp << "\t";
    275               }
    276               //cout << endl;
    277             }
    278             //cout << endl;
    279           }
    280         }
    281       }
    282     }
    283     // 5. write final matrix to file
    284     line = path;
    285     line.append("/");
    286     line += FRAGMENTPREFIX;
    287     FragmentNumber = FixedDigitNumber(NumberOfMolecules, i);
    288     line += FragmentNumber;
    289     delete(FragmentNumber);
    290     line += HCORRECTIONSUFFIX;
    291     output.open(line.c_str());
    292     output << "Time\t\tTotal\t\tKinetic\t\tNonLocal\tCorrelation\tExchange\tPseudo\t\tHartree\t\t-Gauss\t\tEwald\t\tIonKin\t\tETotal" << endl;
    293     for (int j=0;j<b;j++) {
    294       for(int i=0;i<a;i++)
    295         output << correction[i][j] << "\t";
    296       output << endl;
    297     }
    298     output.close();
    299   }
    300   line = path;
    301   line.append("/");
    302   line += HCORRECTIONSUFFIX;
    303   output.open(line.c_str());
    304   output << "Time\t\tTotal\t\tKinetic\t\tNonLocal\tCorrelation\tExchange\tPseudo\t\tHartree\t\t-Gauss\t\tEwald\t\tIonKin\t\tETotal" << endl;
    305   for (int j=0;j<b;j++) {
    306     for(int i=0;i<a;i++)
    307       output << 0 << "\t";
    308     output << endl;
    309   }
    310   output.close();
    311   // 6. free memory of parsed matrices
    312   FitConstant = (double ***) Malloc(sizeof(double **)*a, "MoleculeListClass::AddHydrogenCorrection: ***FitConstant");
    313   for (int k=0;k<3;k++) {
    314     FitConstant[k] = (double **) Malloc(sizeof(double *)*a, "MoleculeListClass::AddHydrogenCorrection: **FitConstant[]");
    315     for (int i=a;i--;) {
    316       FitConstant[k][i] = (double *) Malloc(sizeof(double)*b, "MoleculeListClass::AddHydrogenCorrection: *FitConstant[][]");
    317     }
    318   }
    319   cout << "done." << endl;
    320   return true;
     144        atom *Walker = NULL;
     145        atom *Runner = NULL;
     146        double ***FitConstant = NULL, **correction = NULL;
     147        int a,b;
     148        ofstream output;
     149        ifstream input;
     150        string line;
     151        stringstream zeile;
     152        double distance;
     153        char ParsedLine[1023];
     154        double tmp;
     155        char *FragmentNumber = NULL;
     156
     157        cout << Verbose(1) << "Saving hydrogen saturation correction ... ";
     158        // 0. parse in fit constant files that should have the same dimension as the final energy files
     159        // 0a. find dimension of matrices with constants
     160        line = path;
     161        line.append("/");
     162        line += FRAGMENTPREFIX;
     163        line += "1";
     164        line += FITCONSTANTSUFFIX;
     165        input.open(line.c_str());
     166        if (input == NULL) {
     167                cerr << endl << "Unable to open " << line << ", is the directory correct?" << endl;
     168                return false;
     169        }
     170        a=0;
     171        b=-1; // we overcount by one
     172        while (!input.eof()) {
     173                input.getline(ParsedLine, 1023);
     174                zeile.str(ParsedLine);
     175                int i=0;
     176                while (!zeile.eof()) {
     177                        zeile >> distance;
     178                        i++;
     179                }
     180                if (i > a)
     181                        a = i;
     182                b++;
     183        }
     184        cout << "I recognized " << a << " columns and " << b << " rows, ";
     185        input.close();
     186       
     187        // 0b. allocate memory for constants
     188        FitConstant = (double ***) Malloc(sizeof(double **)*3, "MoleculeListClass::AddHydrogenCorrection: ***FitConstant");
     189        for (int k=0;k<3;k++) {
     190                FitConstant[k] = (double **) Malloc(sizeof(double *)*a, "MoleculeListClass::AddHydrogenCorrection: **FitConstant[]");
     191                for (int i=a;i--;) {
     192                        FitConstant[k][i] = (double *) Malloc(sizeof(double)*b, "MoleculeListClass::AddHydrogenCorrection: *FitConstant[][]");
     193                }
     194        }
     195        // 0c. parse in constants
     196        for (int i=0;i<3;i++) {
     197                line = path;
     198                line.append("/");
     199                line += FRAGMENTPREFIX;
     200                sprintf(ParsedLine, "%d", i+1);
     201                line += ParsedLine;
     202                line += FITCONSTANTSUFFIX;
     203                input.open(line.c_str());
     204                if (input == NULL) {
     205                        cerr << endl << "Unable to open " << line << ", is the directory correct?" << endl;
     206                        return false;
     207                }
     208                int k = 0,l;
     209                while ((!input.eof()) && (k < b)) {
     210                        input.getline(ParsedLine, 1023);
     211                        //cout << "Current Line: " << ParsedLine << endl;
     212                        zeile.str(ParsedLine);
     213                        zeile.clear();
     214                        l = 0;
     215                        while ((!zeile.eof()) && (l < a)) {
     216                                zeile >> FitConstant[i][l][k];
     217                                //cout << FitConstant[i][l][k] << "\t";
     218                                l++;
     219                        }
     220                        //cout << endl;
     221                        k++;
     222                }
     223                input.close();
     224        }
     225        for(int k=0;k<3;k++) {
     226                cout << "Constants " << k << ":" << endl;
     227                for (int j=0;j<b;j++) {
     228                        for (int i=0;i<a;i++) {
     229                                cout << FitConstant[k][i][j] << "\t";
     230                        }
     231                        cout << endl;
     232                }
     233                cout << endl;
     234        }
     235       
     236        // 0d. allocate final correction matrix
     237        correction = (double **) Malloc(sizeof(double *)*a, "MoleculeListClass::AddHydrogenCorrection: **correction");
     238        for (int i=a;i--;)
     239                correction[i] = (double *) Malloc(sizeof(double)*b, "MoleculeListClass::AddHydrogenCorrection: *correction[]");
     240                               
     241        // 1a. go through every molecule in the list
     242        for(int i=NumberOfMolecules;i--;) {
     243                // 1b. zero final correction matrix
     244                for (int k=a;k--;)
     245                        for (int j=b;j--;)
     246                                correction[k][j] = 0.;
     247                // 2. take every hydrogen that is a saturated one
     248                Walker = ListOfMolecules[i]->start;
     249                while (Walker->next != ListOfMolecules[i]->end) {
     250                        Walker = Walker->next;
     251                        //cout << Verbose(1) << "Walker: " << *Walker << " with first bond " << *ListOfMolecules[i]->ListOfBondsPerAtom[Walker->nr][0] << "." << endl;
     252                        if ((Walker->type->Z == 1) && ((Walker->father == NULL) || (Walker->father->type->Z != 1))) { // if it's a hydrogen
     253                                Runner = ListOfMolecules[i]->start;
     254                                while (Runner->next != ListOfMolecules[i]->end) {
     255                                        Runner = Runner->next;
     256                                        //cout << Verbose(2) << "Runner: " << *Runner << " with first bond " << *ListOfMolecules[i]->ListOfBondsPerAtom[Runner->nr][0] << "." << endl;
     257                                        // 3. take every other hydrogen that is the not the first and not bound to same bonding partner
     258                                        if ((Runner->type->Z == 1) && (Runner->nr > Walker->nr) && (ListOfMolecules[i]->ListOfBondsPerAtom[Runner->nr][0]->GetOtherAtom(Runner) != ListOfMolecules[i]->ListOfBondsPerAtom[Walker->nr][0]->GetOtherAtom(Walker))) {      // (hydrogens have only one bonding partner!)
     259                                                // 4. evaluate the morse potential for each matrix component and add up
     260                                                distance = Runner->x.Distance(&Walker->x);
     261                                                //cout << "Fragment " << i << ": " << *Runner << "<= " << distance << "=>" << *Walker << ":" << endl;
     262                                                for(int k=0;k<a;k++) {
     263                                                        for (int j=0;j<b;j++) {
     264                                                                switch(k) {
     265                                                                case 1:
     266                                                                case 7:
     267                                                                case 11:
     268                                                                        tmp = pow(FitConstant[0][k][j] * ( 1. - exp(-FitConstant[1][k][j] * (distance - FitConstant[2][k][j]) ) ),2);
     269                                                                        break;
     270                                                                default:
     271                                                                        tmp = FitConstant[0][k][j] * pow( distance,     FitConstant[1][k][j]) + FitConstant[2][k][j];
     272                                                                };
     273                                                                correction[k][j] -= tmp;                // ground state is actually lower (disturbed by additional interaction)
     274                                                                //cout << tmp << "\t";
     275                                                        }
     276                                                        //cout << endl;
     277                                                }
     278                                                //cout << endl;
     279                                        }
     280                                }
     281                        }
     282                }
     283                // 5. write final matrix to file
     284                line = path;
     285                line.append("/");
     286                line += FRAGMENTPREFIX;
     287                FragmentNumber = FixedDigitNumber(NumberOfMolecules, i);
     288                line += FragmentNumber;
     289                delete(FragmentNumber);
     290                line += HCORRECTIONSUFFIX;
     291                output.open(line.c_str());
     292                output << "Time\t\tTotal\t\tKinetic\t\tNonLocal\tCorrelation\tExchange\tPseudo\t\tHartree\t\t-Gauss\t\tEwald\t\tIonKin\t\tETotal" << endl;
     293                for (int j=0;j<b;j++) {
     294                        for(int i=0;i<a;i++)
     295                                output << correction[i][j] << "\t";
     296                        output << endl;
     297                }
     298                output.close();
     299        }
     300        line = path;
     301        line.append("/");
     302        line += HCORRECTIONSUFFIX;
     303        output.open(line.c_str());
     304        output << "Time\t\tTotal\t\tKinetic\t\tNonLocal\tCorrelation\tExchange\tPseudo\t\tHartree\t\t-Gauss\t\tEwald\t\tIonKin\t\tETotal" << endl;
     305        for (int j=0;j<b;j++) {
     306                for(int i=0;i<a;i++)
     307                        output << 0 << "\t";
     308                output << endl;
     309        }
     310        output.close();
     311        // 6. free memory of parsed matrices
     312        FitConstant = (double ***) Malloc(sizeof(double **)*a, "MoleculeListClass::AddHydrogenCorrection: ***FitConstant");
     313        for (int k=0;k<3;k++) {
     314                FitConstant[k] = (double **) Malloc(sizeof(double *)*a, "MoleculeListClass::AddHydrogenCorrection: **FitConstant[]");
     315                for (int i=a;i--;) {
     316                        FitConstant[k][i] = (double *) Malloc(sizeof(double)*b, "MoleculeListClass::AddHydrogenCorrection: *FitConstant[][]");
     317                }
     318        }
     319        cout << "done." << endl;
     320        return true;
    321321};
    322322
     
    329329bool MoleculeListClass::StoreForcesFile(ofstream *out, char *path, int *SortIndex)
    330330{
    331   bool status = true;
    332   ofstream ForcesFile;
    333   stringstream line;
    334   atom *Walker = NULL;
    335   element *runner = NULL;
    336 
    337   // open file for the force factors
    338   *out << Verbose(1) << "Saving  force factors ... ";
    339   line << path << "/" << FRAGMENTPREFIX << FORCESFILE;
    340   ForcesFile.open(line.str().c_str(), ios::out);
    341   if (ForcesFile != NULL) {
    342     //cout << Verbose(1) << "Final AtomicForcesList: ";
    343     //output << prefix << "Forces" << endl;
    344     for(int j=0;j<NumberOfMolecules;j++) {
    345       //if (TEList[j] != 0) {
    346       runner = ListOfMolecules[j]->elemente->start;
    347       while (runner->next != ListOfMolecules[j]->elemente->end) { // go through every element
    348         runner = runner->next;
    349         if (ListOfMolecules[j]->ElementsInMolecule[runner->Z]) { // if this element got atoms
    350           Walker = ListOfMolecules[j]->start;
    351           while (Walker->next != ListOfMolecules[j]->end) { // go through every atom of this element
    352             Walker = Walker->next;
    353             if (Walker->type->Z == runner->Z) {
    354               if ((Walker->GetTrueFather() != NULL) && (Walker->GetTrueFather() != Walker)) {// if there is a rea
    355                 //cout << "Walker is " << *Walker << " with true father " << *( Walker->GetTrueFather()) << ", it
    356                 ForcesFile <<  SortIndex[Walker->GetTrueFather()->nr] << "\t";
    357                 } else  // otherwise a -1 to indicate an added saturation hydrogen
    358                   ForcesFile << "-1\t";
    359               }
    360             }
    361           }
    362       }
    363       ForcesFile << endl;
    364     }
    365     ForcesFile.close();
    366     *out << Verbose(1) << "done." << endl;
    367   } else {
    368     status = false;
    369     *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;
    370   }
    371   ForcesFile.close();
    372  
    373   return status;
     331        bool status = true;
     332        ofstream ForcesFile;
     333        stringstream line;
     334        atom *Walker = NULL;
     335        element *runner = NULL;
     336
     337        // open file for the force factors
     338        *out << Verbose(1) << "Saving   force factors ... ";
     339        line << path << "/" << FRAGMENTPREFIX << FORCESFILE;
     340        ForcesFile.open(line.str().c_str(), ios::out);
     341        if (ForcesFile != NULL) {
     342                //cout << Verbose(1) << "Final AtomicForcesList: ";
     343                //output << prefix << "Forces" << endl;
     344                for(int j=0;j<NumberOfMolecules;j++) {
     345                        //if (TEList[j] != 0) {
     346                        runner = ListOfMolecules[j]->elemente->start;
     347                        while (runner->next != ListOfMolecules[j]->elemente->end) { // go through every element
     348                                runner = runner->next;
     349                                if (ListOfMolecules[j]->ElementsInMolecule[runner->Z]) { // if this element got atoms
     350                                        Walker = ListOfMolecules[j]->start;
     351                                        while (Walker->next != ListOfMolecules[j]->end) { // go through every atom of this element
     352                                                Walker = Walker->next;
     353                                                if (Walker->type->Z == runner->Z) {
     354                                                        if ((Walker->GetTrueFather() != NULL) && (Walker->GetTrueFather() != Walker)) {// if there is a rea
     355                                                                //cout << "Walker is " << *Walker << " with true father " << *( Walker->GetTrueFather()) << ", it
     356                                                                ForcesFile <<   SortIndex[Walker->GetTrueFather()->nr] << "\t";
     357                                                                } else  // otherwise a -1 to indicate an added saturation hydrogen
     358                                                                        ForcesFile << "-1\t";
     359                                                        }
     360                                                }
     361                                        }
     362                        }
     363                        ForcesFile << endl;
     364                }
     365                ForcesFile.close();
     366                *out << Verbose(1) << "done." << endl;
     367        } else {
     368                status = false;
     369                *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;
     370        }
     371        ForcesFile.close();
     372       
     373        return status;
    374374};
    375375
     
    382382bool MoleculeListClass::OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex)
    383383{
    384   ofstream outputFragment;
    385   char FragmentName[MAXSTRINGSIZE];
    386   char PathBackup[MAXSTRINGSIZE];
    387   bool result = true;
    388   bool intermediateResult = true;
    389   atom *Walker = NULL;
    390   Vector BoxDimension;
    391   char *FragmentNumber = NULL;
    392   char *path = NULL;
    393   int FragmentCounter = 0;
    394   ofstream output;
    395  
    396   // store the fragments as config and as xyz
    397   for(int i=0;i<NumberOfMolecules;i++) {
    398     // save default path as it is changed for each fragment
    399     path = configuration->GetDefaultPath();
    400     if (path != NULL)
    401       strcpy(PathBackup, path);
    402     else
    403       cerr << "OutputConfigForListOfFragments: NULL default path obtained from config!" << endl;
    404 
    405     // correct periodic
    406     ListOfMolecules[i]->ScanForPeriodicCorrection(out);
    407 
    408     // output xyz file
    409     FragmentNumber = FixedDigitNumber(NumberOfMolecules, FragmentCounter++);
    410     sprintf(FragmentName, "%s/%s%s.conf.xyz", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);
    411     outputFragment.open(FragmentName, ios::out);
    412     *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter-1 << " as XYZ ...";
    413     if ((intermediateResult = ListOfMolecules[i]->OutputXYZ(&outputFragment)))
    414       *out << " done." << endl;
    415     else
    416       *out << " failed." << endl;
    417     result = result && intermediateResult;
    418     outputFragment.close();
    419     outputFragment.clear();
    420 
    421     // list atoms in fragment for debugging
    422     *out << Verbose(2) << "Contained atoms: ";
    423     Walker = ListOfMolecules[i]->start;
    424     while (Walker->next != ListOfMolecules[i]->end) {
    425       Walker = Walker->next;
    426       *out << Walker->Name << " ";
    427     }
    428     *out << endl;
    429    
    430     // center on edge
    431     ListOfMolecules[i]->CenterEdge(out, &BoxDimension);
    432     ListOfMolecules[i]->SetBoxDimension(&BoxDimension);  // update Box of atoms by boundary
    433     int j = -1;
    434     for (int k=0;k<NDIM;k++) {
    435       j += k+1;
    436       BoxDimension.x[k] = 2.5* (configuration->GetIsAngstroem() ? 1. : 1./AtomicLengthToAngstroem);
    437       ListOfMolecules[i]->cell_size[j] += BoxDimension.x[k]*2.;
    438     }
    439     ListOfMolecules[i]->Translate(&BoxDimension);
    440 
    441     // also calculate necessary orbitals
    442     ListOfMolecules[i]->CountElements();  // this is a bugfix, atoms should should actually be added correctly to this fragment
    443     ListOfMolecules[i]->CalculateOrbitals(*configuration);
    444    
    445     // change path in config
    446     //strcpy(PathBackup, configuration->configpath);
    447     sprintf(FragmentName, "%s/%s%s/", PathBackup, FRAGMENTPREFIX, FragmentNumber);
    448     configuration->SetDefaultPath(FragmentName);
    449    
    450     // and save as config
    451     sprintf(FragmentName, "%s/%s%s.conf", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);
    452     *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter-1 << " as config ...";
    453     if ((intermediateResult = configuration->Save(FragmentName, ListOfMolecules[i]->elemente, ListOfMolecules[i])))
    454       *out << " done." << endl;
    455     else
    456       *out << " failed." << endl;
    457     result = result && intermediateResult;
    458 
    459     // restore old config
    460     configuration->SetDefaultPath(PathBackup);
    461 
    462 
    463     // and save as mpqc input file
    464     sprintf(FragmentName, "%s/%s%s.conf", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);
    465     *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter-1 << " as mpqc input ...";
    466     if ((intermediateResult = configuration->SaveMPQC(FragmentName, ListOfMolecules[i])))
    467       *out << " done." << endl;
    468     else
    469       *out << " failed." << endl;
    470      
    471     result = result && intermediateResult;
    472     //outputFragment.close();
    473     //outputFragment.clear();
    474     delete(FragmentNumber);
    475     //Free((void **)&FragmentNumber, "MoleculeListClass::OutputConfigForListOfFragments: *FragmentNumber");
    476   }
    477   cout << " done." << endl;
    478  
    479   // printing final number
    480   *out << "Final number of fragments: " << FragmentCounter << "." << endl;
    481      
    482   return result;
     384        ofstream outputFragment;
     385        char FragmentName[MAXSTRINGSIZE];
     386        char PathBackup[MAXSTRINGSIZE];
     387        bool result = true;
     388        bool intermediateResult = true;
     389        atom *Walker = NULL;
     390        Vector BoxDimension;
     391        char *FragmentNumber = NULL;
     392        char *path = NULL;
     393        int FragmentCounter = 0;
     394        ofstream output;
     395       
     396        // store the fragments as config and as xyz
     397        for(int i=0;i<NumberOfMolecules;i++) {
     398                // save default path as it is changed for each fragment
     399                path = configuration->GetDefaultPath();
     400                if (path != NULL)
     401                        strcpy(PathBackup, path);
     402                else
     403                        cerr << "OutputConfigForListOfFragments: NULL default path obtained from config!" << endl;
     404
     405                // correct periodic
     406                ListOfMolecules[i]->ScanForPeriodicCorrection(out);
     407
     408                // output xyz file
     409                FragmentNumber = FixedDigitNumber(NumberOfMolecules, FragmentCounter++);
     410                sprintf(FragmentName, "%s/%s%s.conf.xyz", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);
     411                outputFragment.open(FragmentName, ios::out);
     412                *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter-1 << " as XYZ ...";
     413                if ((intermediateResult = ListOfMolecules[i]->OutputXYZ(&outputFragment)))
     414                        *out << " done." << endl;
     415                else
     416                        *out << " failed." << endl;
     417                result = result && intermediateResult;
     418                outputFragment.close();
     419                outputFragment.clear();
     420
     421                // list atoms in fragment for debugging
     422                *out << Verbose(2) << "Contained atoms: ";
     423                Walker = ListOfMolecules[i]->start;
     424                while (Walker->next != ListOfMolecules[i]->end) {
     425                        Walker = Walker->next;
     426                        *out << Walker->Name << " ";
     427                }
     428                *out << endl;
     429               
     430                // center on edge
     431                ListOfMolecules[i]->CenterEdge(out, &BoxDimension);
     432                ListOfMolecules[i]->SetBoxDimension(&BoxDimension);     // update Box of atoms by boundary
     433                int j = -1;
     434                for (int k=0;k<NDIM;k++) {
     435                        j += k+1;
     436                        BoxDimension.x[k] = 2.5* (configuration->GetIsAngstroem() ? 1. : 1./AtomicLengthToAngstroem);
     437                        ListOfMolecules[i]->cell_size[j] += BoxDimension.x[k]*2.;
     438                }
     439                ListOfMolecules[i]->Translate(&BoxDimension);
     440
     441                // also calculate necessary orbitals
     442                ListOfMolecules[i]->CountElements();    // this is a bugfix, atoms should should actually be added correctly to this fragment
     443                ListOfMolecules[i]->CalculateOrbitals(*configuration);
     444               
     445                // change path in config
     446                //strcpy(PathBackup, configuration->configpath);
     447                sprintf(FragmentName, "%s/%s%s/", PathBackup, FRAGMENTPREFIX, FragmentNumber);
     448                configuration->SetDefaultPath(FragmentName);
     449               
     450                // and save as config
     451                sprintf(FragmentName, "%s/%s%s.conf", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);
     452                *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter-1 << " as config ...";
     453                if ((intermediateResult = configuration->Save(FragmentName, ListOfMolecules[i]->elemente, ListOfMolecules[i])))
     454                        *out << " done." << endl;
     455                else
     456                        *out << " failed." << endl;
     457                result = result && intermediateResult;
     458
     459                // restore old config
     460                configuration->SetDefaultPath(PathBackup);
     461
     462
     463                // and save as mpqc input file
     464                sprintf(FragmentName, "%s/%s%s.conf", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);
     465                *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter-1 << " as mpqc input ...";
     466                if ((intermediateResult = configuration->SaveMPQC(FragmentName, ListOfMolecules[i])))
     467                        *out << " done." << endl;
     468                else
     469                        *out << " failed." << endl;
     470                       
     471                result = result && intermediateResult;
     472                //outputFragment.close();
     473                //outputFragment.clear();
     474                delete(FragmentNumber);
     475                //Free((void **)&FragmentNumber, "MoleculeListClass::OutputConfigForListOfFragments: *FragmentNumber");
     476        }
     477        cout << " done." << endl;
     478       
     479        // printing final number
     480        *out << "Final number of fragments: " << FragmentCounter << "." << endl;
     481                       
     482        return result;
    483483};
    484484
     
    492492MoleculeLeafClass::MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf = NULL)
    493493{
    494 //  if (Up != NULL)
    495 //    if (Up->DownLeaf == NULL) // are we the first down leaf for the upper leaf?
    496 //      Up->DownLeaf = this;
    497 //  UpLeaf = Up;
    498 //  DownLeaf = NULL;
    499   Leaf = NULL;
    500   previous = PreviousLeaf;
    501   if (previous != NULL) {
    502     MoleculeLeafClass *Walker = previous->next;
    503     previous->next = this;
    504     next = Walker;
    505   } else {
    506     next = NULL;
    507   }
     494//      if (Up != NULL)
     495//              if (Up->DownLeaf == NULL) // are we the first down leaf for the upper leaf?
     496//                      Up->DownLeaf = this;
     497//      UpLeaf = Up;
     498//      DownLeaf = NULL;
     499        Leaf = NULL;
     500        previous = PreviousLeaf;
     501        if (previous != NULL) {
     502                MoleculeLeafClass *Walker = previous->next;
     503                previous->next = this;
     504                next = Walker;
     505        } else {
     506                next = NULL;
     507        }
    508508};
    509509
     
    512512MoleculeLeafClass::~MoleculeLeafClass()
    513513{
    514 //  if (DownLeaf != NULL) {// drop leaves further down
    515 //    MoleculeLeafClass *Walker = DownLeaf;
    516 //    MoleculeLeafClass *Next;
    517 //    do {
    518 //      Next = Walker->NextLeaf;
    519 //      delete(Walker);
    520 //      Walker = Next;
    521 //    } while (Walker != NULL);
    522 //    // Last Walker sets DownLeaf automatically to NULL
    523 //  }
    524   // remove the leaf itself
    525   if (Leaf != NULL) {
    526     delete(Leaf);
    527     Leaf = NULL;
    528   }
    529   // remove this Leaf from level list
    530   if (previous != NULL) 
    531     previous->next = next;
    532 //  } else { // we are first in list (connects to UpLeaf->DownLeaf)
    533 //    if ((NextLeaf != NULL) && (NextLeaf->UpLeaf == NULL))
    534 //      NextLeaf->UpLeaf = UpLeaf;  // either null as we are top level or the upleaf of the first node
    535 //    if (UpLeaf != NULL)
    536 //      UpLeaf->DownLeaf = NextLeaf;  // either null as we are only leaf or NextLeaf if we are just the first
    537 //  }
    538 //  UpLeaf = NULL;
    539   if (next != NULL) // are we last in list
    540     next->previous = previous;
    541   next = NULL;
    542   previous = NULL;
     514//      if (DownLeaf != NULL) {// drop leaves further down
     515//              MoleculeLeafClass *Walker = DownLeaf;
     516//              MoleculeLeafClass *Next;
     517//              do {
     518//                      Next = Walker->NextLeaf;
     519//                      delete(Walker);
     520//                      Walker = Next;
     521//              } while (Walker != NULL);
     522//              // Last Walker sets DownLeaf automatically to NULL
     523//      }
     524        // remove the leaf itself
     525        if (Leaf != NULL) {
     526                delete(Leaf);
     527                Leaf = NULL;
     528        }
     529        // remove this Leaf from level list
     530        if (previous != NULL)   
     531                previous->next = next;
     532//      } else { // we are first in list (connects to UpLeaf->DownLeaf)
     533//              if ((NextLeaf != NULL) && (NextLeaf->UpLeaf == NULL))
     534//                      NextLeaf->UpLeaf = UpLeaf;      // either null as we are top level or the upleaf of the first node
     535//              if (UpLeaf != NULL)
     536//                      UpLeaf->DownLeaf = NextLeaf;    // either null as we are only leaf or NextLeaf if we are just the first
     537//      }
     538//      UpLeaf = NULL;
     539        if (next != NULL) // are we last in list
     540                next->previous = previous;
     541        next = NULL;
     542        previous = NULL;
    543543};
    544544
     
    550550bool MoleculeLeafClass::AddLeaf(molecule *ptr, MoleculeLeafClass *Previous)
    551551{
    552   return false;
     552        return false;
    553553};
    554554
     
    564564bool MoleculeLeafClass::FillBondStructureFromReference(ofstream *out, molecule *reference, int &FragmentCounter, atom ***&ListOfLocalAtoms, bool FreeList)
    565565{
    566   atom *Walker = NULL, *OtherWalker = NULL;
    567   bond *Binder = NULL;
    568   bool status = true;
    569   int AtomNo;
    570 
    571   *out << Verbose(1) << "Begin of FillBondStructureFromReference." << endl;
    572   // fill ListOfLocalAtoms if NULL was given
    573   if (!FillListOfLocalAtoms(out, ListOfLocalAtoms, FragmentCounter, reference->AtomCount, FreeList)) {
    574     *out << Verbose(1) << "Filling of ListOfLocalAtoms failed." << endl;
    575     return false;
    576   }
    577  
    578   if (status) {
    579     *out << Verbose(1) << "Creating adjacency list for subgraph " << this << "." << endl;
    580     Walker = Leaf->start;
    581     while (Walker->next != Leaf->end) {
    582       Walker = Walker->next;
    583       AtomNo = Walker->GetTrueFather()->nr;  // global id of the current walker
    584       for(int i=0;i<reference->NumberOfBondsPerAtom[AtomNo];i++) { // go through father's bonds and copy them all
    585         Binder = reference->ListOfBondsPerAtom[AtomNo][i];
    586         OtherWalker = ListOfLocalAtoms[FragmentCounter][Binder->GetOtherAtom(Walker->GetTrueFather())->nr];    // local copy of current bond partner of walker
    587         if (OtherWalker != NULL) {
    588           if (OtherWalker->nr > Walker->nr)
    589           Leaf->AddBond(Walker, OtherWalker, Binder->BondDegree);
    590         } else {
    591           *out << Verbose(1) << "OtherWalker = ListOfLocalAtoms[" << FragmentCounter << "][" << Binder->GetOtherAtom(Walker->GetTrueFather())->nr << "] is NULL!" << endl;
    592           status = false;
    593         }
    594       }
    595     }
    596     Leaf->CreateListOfBondsPerAtom(out);
    597     FragmentCounter++;
    598     if (next != NULL)
    599       status = next->FillBondStructureFromReference(out, reference, FragmentCounter, ListOfLocalAtoms);
    600     FragmentCounter--;
    601   }
    602  
    603   if ((FreeList) && (ListOfLocalAtoms != NULL)) {
    604     // free the index lookup list
    605     Free((void **)&ListOfLocalAtoms[FragmentCounter], "MoleculeLeafClass::FillBondStructureFromReference - **ListOfLocalAtoms[]");
    606     if (FragmentCounter == 0) // first fragments frees the initial pointer to list
    607       Free((void **)&ListOfLocalAtoms, "MoleculeLeafClass::FillBondStructureFromReference - ***ListOfLocalAtoms");
    608   }
    609   FragmentCounter--;
    610   *out << Verbose(1) << "End of FillBondStructureFromReference." << endl;
    611   return status;
     566        atom *Walker = NULL, *OtherWalker = NULL;
     567        bond *Binder = NULL;
     568        bool status = true;
     569        int AtomNo;
     570
     571        *out << Verbose(1) << "Begin of FillBondStructureFromReference." << endl;
     572        // fill ListOfLocalAtoms if NULL was given
     573        if (!FillListOfLocalAtoms(out, ListOfLocalAtoms, FragmentCounter, reference->AtomCount, FreeList)) {
     574                *out << Verbose(1) << "Filling of ListOfLocalAtoms failed." << endl;
     575                return false;
     576        }
     577       
     578        if (status) {
     579                *out << Verbose(1) << "Creating adjacency list for subgraph " << this << "." << endl;
     580                Walker = Leaf->start;
     581                while (Walker->next != Leaf->end) {
     582                        Walker = Walker->next;
     583                        AtomNo = Walker->GetTrueFather()->nr;   // global id of the current walker
     584                        for(int i=0;i<reference->NumberOfBondsPerAtom[AtomNo];i++) { // go through father's bonds and copy them all
     585                                Binder = reference->ListOfBondsPerAtom[AtomNo][i];
     586                                OtherWalker = ListOfLocalAtoms[FragmentCounter][Binder->GetOtherAtom(Walker->GetTrueFather())->nr];             // local copy of current bond partner of walker
     587                                if (OtherWalker != NULL) {
     588                                        if (OtherWalker->nr > Walker->nr)
     589                                        Leaf->AddBond(Walker, OtherWalker, Binder->BondDegree);
     590                                } else {
     591                                        *out << Verbose(1) << "OtherWalker = ListOfLocalAtoms[" << FragmentCounter << "][" << Binder->GetOtherAtom(Walker->GetTrueFather())->nr << "] is NULL!" << endl;
     592                                        status = false;
     593                                }
     594                        }
     595                }
     596                Leaf->CreateListOfBondsPerAtom(out);
     597                FragmentCounter++;
     598                if (next != NULL)
     599                        status = next->FillBondStructureFromReference(out, reference, FragmentCounter, ListOfLocalAtoms);
     600                FragmentCounter--;
     601        }
     602       
     603        if ((FreeList) && (ListOfLocalAtoms != NULL)) {
     604                // free the index lookup list
     605                Free((void **)&ListOfLocalAtoms[FragmentCounter], "MoleculeLeafClass::FillBondStructureFromReference - **ListOfLocalAtoms[]");
     606                if (FragmentCounter == 0) // first fragments frees the initial pointer to list
     607                        Free((void **)&ListOfLocalAtoms, "MoleculeLeafClass::FillBondStructureFromReference - ***ListOfLocalAtoms");
     608        }
     609        FragmentCounter--;
     610        *out << Verbose(1) << "End of FillBondStructureFromReference." << endl;
     611        return status;
    612612};
    613613
     
    622622bool MoleculeLeafClass::FillRootStackForSubgraphs(ofstream *out, KeyStack *&RootStack, bool *AtomMask, int &FragmentCounter)
    623623{
    624   atom *Walker = NULL, *Father = NULL;
    625 
    626   if (RootStack != NULL) {
    627     // find first root candidates
    628     if (&(RootStack[FragmentCounter]) != NULL) {
    629       RootStack[FragmentCounter].clear(); 
    630       Walker = Leaf->start;
    631       while (Walker->next != Leaf->end) { // go through all (non-hydrogen) atoms
    632         Walker = Walker->next;
    633         Father = Walker->GetTrueFather();
    634         if (AtomMask[Father->nr]) // apply mask
    635     #ifdef ADDHYDROGEN
    636           if (Walker->type->Z != 1) // skip hydrogen
    637     #endif
    638             RootStack[FragmentCounter].push_front(Walker->nr);
    639       }
    640       if (next != NULL)
    641         next->FillRootStackForSubgraphs(out, RootStack, AtomMask, ++FragmentCounter);
    642     }  else {
    643       *out << Verbose(1) << "Rootstack[" << FragmentCounter  << "] is NULL." << endl;
    644       return false;
    645     }
    646     FragmentCounter--;
    647     return true;
    648   } else {
    649     *out << Verbose(1) << "Rootstack is NULL." << endl;
    650     return false;
    651   }
     624        atom *Walker = NULL, *Father = NULL;
     625
     626        if (RootStack != NULL) {
     627                // find first root candidates
     628                if (&(RootStack[FragmentCounter]) != NULL) {
     629                        RootStack[FragmentCounter].clear();     
     630                        Walker = Leaf->start;
     631                        while (Walker->next != Leaf->end) { // go through all (non-hydrogen) atoms
     632                                Walker = Walker->next;
     633                                Father = Walker->GetTrueFather();
     634                                if (AtomMask[Father->nr]) // apply mask
     635                #ifdef ADDHYDROGEN
     636                                        if (Walker->type->Z != 1) // skip hydrogen
     637                #endif
     638                                                RootStack[FragmentCounter].push_front(Walker->nr);
     639                        }
     640                        if (next != NULL)
     641                                next->FillRootStackForSubgraphs(out, RootStack, AtomMask, ++FragmentCounter);
     642                }       else {
     643                        *out << Verbose(1) << "Rootstack[" << FragmentCounter   << "] is NULL." << endl;
     644                        return false;
     645                }
     646                FragmentCounter--;
     647                return true;
     648        } else {
     649                *out << Verbose(1) << "Rootstack is NULL." << endl;
     650                return false;
     651        }
    652652};
    653653
     
    662662bool MoleculeLeafClass::FillListOfLocalAtoms(ofstream *out, atom ***&ListOfLocalAtoms, const int FragmentCounter, const int GlobalAtomCount, bool &FreeList)
    663663{
    664   bool status = true;
    665  
    666   int Counter = Count();
    667   if (ListOfLocalAtoms == NULL) { // allocated initial pointer
    668     // allocate and set each field to NULL
    669     ListOfLocalAtoms = (atom ***) Malloc(sizeof(atom **)*Counter, "MoleculeLeafClass::FillBondStructureFromReference - ***ListOfLocalAtoms");
    670     if (ListOfLocalAtoms != NULL) {
    671       for (int i=Counter;i--;)
    672         ListOfLocalAtoms[i] = NULL;
    673       FreeList = FreeList && true;
    674     } else
    675       status = false;
    676   }
    677  
    678   if ((ListOfLocalAtoms != NULL) && (ListOfLocalAtoms[FragmentCounter] == NULL)) { // allocate and fill list of this fragment/subgraph
    679     status = status && CreateFatherLookupTable(out, Leaf->start, Leaf->end, ListOfLocalAtoms[FragmentCounter], GlobalAtomCount);
    680     FreeList = FreeList && true;
    681   }
    682  
    683   return status;
     664        bool status = true;
     665       
     666        int Counter = Count();
     667        if (ListOfLocalAtoms == NULL) { // allocated initial pointer
     668                // allocate and set each field to NULL
     669                ListOfLocalAtoms = (atom ***) Malloc(sizeof(atom **)*Counter, "MoleculeLeafClass::FillBondStructureFromReference - ***ListOfLocalAtoms");
     670                if (ListOfLocalAtoms != NULL) {
     671                        for (int i=Counter;i--;)
     672                                ListOfLocalAtoms[i] = NULL;
     673                        FreeList = FreeList && true;
     674                } else
     675                        status = false;
     676        }
     677       
     678        if ((ListOfLocalAtoms != NULL) && (ListOfLocalAtoms[FragmentCounter] == NULL)) { // allocate and fill list of this fragment/subgraph
     679                status = status && CreateFatherLookupTable(out, Leaf->start, Leaf->end, ListOfLocalAtoms[FragmentCounter], GlobalAtomCount);
     680                FreeList = FreeList && true;
     681        }
     682       
     683        return status;
    684684};
    685685
     
    696696bool MoleculeLeafClass::AssignKeySetsToFragment(ofstream *out, molecule *reference, Graph *KeySetList, atom ***&ListOfLocalAtoms, Graph **&FragmentList, int &FragmentCounter, bool FreeList)
    697697{
    698   bool status = true;
    699   int KeySetCounter = 0;
    700  
    701   *out << Verbose(1) << "Begin of AssignKeySetsToFragment." << endl;
    702   // fill ListOfLocalAtoms if NULL was given
    703   if (!FillListOfLocalAtoms(out, ListOfLocalAtoms, FragmentCounter, reference->AtomCount, FreeList)) {
    704     *out << Verbose(1) << "Filling of ListOfLocalAtoms failed." << endl;
    705     return false;
    706   }
    707 
    708   // allocate fragment list
    709   if (FragmentList == NULL) {
    710     KeySetCounter = Count();
    711     FragmentList = (Graph **) Malloc(sizeof(Graph *)*KeySetCounter, "MoleculeLeafClass::AssignKeySetsToFragment - **FragmentList");
    712     for(int i=KeySetCounter;i--;)
    713       FragmentList[i] = NULL;
    714     KeySetCounter = 0;
    715   }
    716  
    717   if ((KeySetList != NULL) && (KeySetList->size() != 0)) { // if there are some scanned keysets at all
    718     // assign scanned keysets
    719     if (FragmentList[FragmentCounter] == NULL)
    720       FragmentList[FragmentCounter] = new Graph;
    721     KeySet *TempSet = new KeySet;
    722     for(Graph::iterator runner = KeySetList->begin();runner != KeySetList->end(); runner++) { // key sets contain global numbers!
    723       if ( ListOfLocalAtoms[FragmentCounter][reference->FindAtom(*((*runner).first.begin()))->nr] != NULL) {// as we may assume that that bond structure is unchanged, we only test the first key in each set
    724         // translate keyset to local numbers
    725         for(KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++)
    726           TempSet->insert(ListOfLocalAtoms[FragmentCounter][reference->FindAtom(*sprinter)->nr]->nr);
    727         // insert into FragmentList
    728         FragmentList[FragmentCounter]->insert(GraphPair (*TempSet, pair<int,double>(KeySetCounter++, (*runner).second.second)));
    729       }
    730       TempSet->clear();
    731     }
    732     delete(TempSet);
    733     if (KeySetCounter == 0) {// if there are no keysets, delete the list
    734       *out << Verbose(1) << "KeySetCounter is zero, deleting FragmentList." << endl;
    735       delete(FragmentList[FragmentCounter]);
    736     } else
    737       *out << Verbose(1) << KeySetCounter << " keysets were assigned to subgraph " << FragmentCounter << "." << endl;
    738     FragmentCounter++;
    739     if (next != NULL)
    740       next->AssignKeySetsToFragment(out, reference, KeySetList, ListOfLocalAtoms, FragmentList, FragmentCounter, FreeList);
    741     FragmentCounter--;
    742   } else
    743     *out << Verbose(1) << "KeySetList is NULL or empty." << endl;
    744  
    745   if ((FreeList) && (ListOfLocalAtoms != NULL)) {
    746     // free the index lookup list
    747     Free((void **)&ListOfLocalAtoms[FragmentCounter], "MoleculeLeafClass::AssignKeySetsToFragment - **ListOfLocalAtoms[]");
    748     if (FragmentCounter == 0) // first fragments frees the initial pointer to list
    749       Free((void **)&ListOfLocalAtoms, "MoleculeLeafClass::AssignKeySetsToFragment - ***ListOfLocalAtoms");
    750   }
    751   *out << Verbose(1) << "End of AssignKeySetsToFragment." << endl;
    752   return status;
     698        bool status = true;
     699        int KeySetCounter = 0;
     700       
     701        *out << Verbose(1) << "Begin of AssignKeySetsToFragment." << endl;
     702        // fill ListOfLocalAtoms if NULL was given
     703        if (!FillListOfLocalAtoms(out, ListOfLocalAtoms, FragmentCounter, reference->AtomCount, FreeList)) {
     704                *out << Verbose(1) << "Filling of ListOfLocalAtoms failed." << endl;
     705                return false;
     706        }
     707
     708        // allocate fragment list
     709        if (FragmentList == NULL) {
     710                KeySetCounter = Count();
     711                FragmentList = (Graph **) Malloc(sizeof(Graph *)*KeySetCounter, "MoleculeLeafClass::AssignKeySetsToFragment - **FragmentList");
     712                for(int i=KeySetCounter;i--;)
     713                        FragmentList[i] = NULL;
     714                KeySetCounter = 0;
     715        }
     716       
     717        if ((KeySetList != NULL) && (KeySetList->size() != 0)) { // if there are some scanned keysets at all
     718                // assign scanned keysets
     719                if (FragmentList[FragmentCounter] == NULL)
     720                        FragmentList[FragmentCounter] = new Graph;
     721                KeySet *TempSet = new KeySet;
     722                for(Graph::iterator runner = KeySetList->begin();runner != KeySetList->end(); runner++) { // key sets contain global numbers!
     723                        if ( ListOfLocalAtoms[FragmentCounter][reference->FindAtom(*((*runner).first.begin()))->nr] != NULL) {// as we may assume that that bond structure is unchanged, we only test the first key in each set
     724                                // translate keyset to local numbers
     725                                for(KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++)
     726                                        TempSet->insert(ListOfLocalAtoms[FragmentCounter][reference->FindAtom(*sprinter)->nr]->nr);
     727                                // insert into FragmentList
     728                                FragmentList[FragmentCounter]->insert(GraphPair (*TempSet, pair<int,double>(KeySetCounter++, (*runner).second.second)));
     729                        }
     730                        TempSet->clear();
     731                }
     732                delete(TempSet);
     733                if (KeySetCounter == 0) {// if there are no keysets, delete the list
     734                        *out << Verbose(1) << "KeySetCounter is zero, deleting FragmentList." << endl;
     735                        delete(FragmentList[FragmentCounter]);
     736                } else
     737                        *out << Verbose(1) << KeySetCounter << " keysets were assigned to subgraph " << FragmentCounter << "." << endl;
     738                FragmentCounter++;
     739                if (next != NULL)
     740                        next->AssignKeySetsToFragment(out, reference, KeySetList, ListOfLocalAtoms, FragmentList, FragmentCounter, FreeList);
     741                FragmentCounter--;
     742        } else
     743                *out << Verbose(1) << "KeySetList is NULL or empty." << endl;
     744       
     745        if ((FreeList) && (ListOfLocalAtoms != NULL)) {
     746                // free the index lookup list
     747                Free((void **)&ListOfLocalAtoms[FragmentCounter], "MoleculeLeafClass::AssignKeySetsToFragment - **ListOfLocalAtoms[]");
     748                if (FragmentCounter == 0) // first fragments frees the initial pointer to list
     749                        Free((void **)&ListOfLocalAtoms, "MoleculeLeafClass::AssignKeySetsToFragment - ***ListOfLocalAtoms");
     750        }
     751        *out << Verbose(1) << "End of AssignKeySetsToFragment." << endl;
     752        return status;
    753753};
    754754
     
    762762void MoleculeLeafClass::TranslateIndicesToGlobalIDs(ofstream *out, Graph **FragmentList, int &FragmentCounter, int &TotalNumberOfKeySets, Graph &TotalGraph)
    763763{
    764   *out << Verbose(1) << "Begin of TranslateIndicesToGlobalIDs." << endl;
    765   KeySet *TempSet = new KeySet;
    766   if (FragmentList[FragmentCounter] != NULL) {
    767     for(Graph::iterator runner = FragmentList[FragmentCounter]->begin(); runner != FragmentList[FragmentCounter]->end(); runner++) {
    768       for(KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++)
    769         TempSet->insert((Leaf->FindAtom(*sprinter))->GetTrueFather()->nr);
    770       TotalGraph.insert(GraphPair(*TempSet, pair<int,double>(TotalNumberOfKeySets++, (*runner).second.second)));
    771       TempSet->clear();
    772     }
    773     delete(TempSet);
    774   } else {
    775     *out << Verbose(1) << "FragmentList is NULL." << endl;
    776   }
    777   if (next != NULL)
    778     next->TranslateIndicesToGlobalIDs(out, FragmentList, ++FragmentCounter, TotalNumberOfKeySets, TotalGraph);
    779   FragmentCounter--;
    780   *out << Verbose(1) << "End of TranslateIndicesToGlobalIDs." << endl;
     764        *out << Verbose(1) << "Begin of TranslateIndicesToGlobalIDs." << endl;
     765        KeySet *TempSet = new KeySet;
     766        if (FragmentList[FragmentCounter] != NULL) {
     767                for(Graph::iterator runner = FragmentList[FragmentCounter]->begin(); runner != FragmentList[FragmentCounter]->end(); runner++) {
     768                        for(KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++)
     769                                TempSet->insert((Leaf->FindAtom(*sprinter))->GetTrueFather()->nr);
     770                        TotalGraph.insert(GraphPair(*TempSet, pair<int,double>(TotalNumberOfKeySets++, (*runner).second.second)));
     771                        TempSet->clear();
     772                }
     773                delete(TempSet);
     774        } else {
     775                *out << Verbose(1) << "FragmentList is NULL." << endl;
     776        }
     777        if (next != NULL)
     778                next->TranslateIndicesToGlobalIDs(out, FragmentList, ++FragmentCounter, TotalNumberOfKeySets, TotalGraph);
     779        FragmentCounter--;
     780        *out << Verbose(1) << "End of TranslateIndicesToGlobalIDs." << endl;
    781781};
    782782
     
    786786int MoleculeLeafClass::Count() const
    787787{
    788   if (next != NULL)
    789     return next->Count()+1;
    790   else
    791     return 1;
    792 };
     788        if (next != NULL)
     789                return next->Count()+1;
     790        else
     791                return 1;
     792};
  • src/molecules.cpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    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;
     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;
    5555        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.;
     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.;
    6464};
    6565
     
    6969molecule::~molecule()
    7070{
    71   if (ListOfBondsPerAtom != NULL)
    72     for(int i=AtomCount;i--;)
    73       Free((void **)&ListOfBondsPerAtom[i], "molecule::~molecule: ListOfBondsPerAtom[i]");
    74   Free((void **)&ListOfBondsPerAtom, "molecule::~molecule: ListOfBondsPerAtom");
    75   Free((void **)&NumberOfBondsPerAtom, "molecule::~molecule: NumberOfBondsPerAtom");
    76   CleanupMolecule();
    77   delete(first);
    78   delete(last);
    79   delete(end);
    80   delete(start);
     71        if (ListOfBondsPerAtom != NULL)
     72                for(int i=AtomCount;i--;)
     73                        Free((void **)&ListOfBondsPerAtom[i], "molecule::~molecule: ListOfBondsPerAtom[i]");
     74        Free((void **)&ListOfBondsPerAtom, "molecule::~molecule: ListOfBondsPerAtom");
     75        Free((void **)&NumberOfBondsPerAtom, "molecule::~molecule: NumberOfBondsPerAtom");
     76        CleanupMolecule();
     77        delete(first);
     78        delete(last);
     79        delete(end);
     80        delete(start);
    8181};
    8282
     
    8888bool molecule::AddAtom(atom *pointer)
    8989{
    90   if (pointer != NULL) {
    91     pointer->sort = &pointer->nr;
    92     pointer->nr = last_atom++;  // increase number within molecule
    93     AtomCount++;
    94     if (pointer->type != NULL) {
    95       if (ElementsInMolecule[pointer->type->Z] == 0)
    96         ElementCount++;
    97       ElementsInMolecule[pointer->type->Z]++; // increase number of elements
    98       if (pointer->type->Z != 1)
    99         NoNonHydrogen++;
    100       if (pointer->Name == NULL) {
    101         Free((void **)&pointer->Name, "molecule::AddAtom: *pointer->Name");
    102         pointer->Name = (char *) Malloc(sizeof(char)*6, "molecule::AddAtom: *pointer->Name");
    103         sprintf(pointer->Name, "%2s%02d", pointer->type->symbol, pointer->nr+1);
    104       }
    105     }
    106     return add(pointer, end);
    107   } else
    108     return false;
     90        if (pointer != NULL) {
     91                pointer->sort = &pointer->nr;
     92                pointer->nr = last_atom++;      // increase number within molecule
     93                AtomCount++;
     94                if (pointer->type != NULL) {
     95                        if (ElementsInMolecule[pointer->type->Z] == 0)
     96                                ElementCount++;
     97                        ElementsInMolecule[pointer->type->Z]++; // increase number of elements
     98                        if (pointer->type->Z != 1)
     99                                NoNonHydrogen++;
     100                        if (pointer->Name == NULL) {
     101                                Free((void **)&pointer->Name, "molecule::AddAtom: *pointer->Name");
     102                                pointer->Name = (char *) Malloc(sizeof(char)*6, "molecule::AddAtom: *pointer->Name");
     103                                sprintf(pointer->Name, "%2s%02d", pointer->type->symbol, pointer->nr+1);
     104                        }
     105                }
     106                return add(pointer, end);
     107        } else
     108                return false;
    109109};
    110110
     
    116116atom * molecule::AddCopyAtom(atom *pointer)
    117117{
    118   if (pointer != NULL) {
    119         atom *walker = new atom();
    120         walker->type = pointer->type;   // copy element of atom
    121         walker->x.CopyVector(&pointer->x); // copy coordination
    122     walker->v.CopyVector(&pointer->v); // copy velocity
    123     walker->FixedIon = pointer->FixedIon;
    124     walker->sort = &walker->nr;
    125     walker->nr = last_atom++;  // increase number within molecule
    126     walker->father = pointer; //->GetTrueFather();
    127     walker->Name = (char *) Malloc(sizeof(char)*strlen(pointer->Name)+1, "molecule::AddCopyAtom: *Name");
    128     strcpy (walker->Name, pointer->Name);
    129     add(walker, end);
    130     if ((pointer->type != NULL) && (pointer->type->Z != 1))
    131       NoNonHydrogen++;
    132     AtomCount++;
    133     return walker;
    134   } else
    135     return NULL;
     118        if (pointer != NULL) {
     119                atom *walker = new atom();
     120                walker->type = pointer->type;   // copy element of atom
     121                walker->x.CopyVector(&pointer->x); // copy coordination
     122                walker->v.CopyVector(&pointer->v); // copy velocity
     123                walker->FixedIon = pointer->FixedIon;
     124                walker->sort = &walker->nr;
     125                walker->nr = last_atom++;       // increase number within molecule
     126                walker->father = pointer; //->GetTrueFather();
     127                walker->Name = (char *) Malloc(sizeof(char)*strlen(pointer->Name)+1, "molecule::AddCopyAtom: *Name");
     128                strcpy (walker->Name, pointer->Name);
     129                add(walker, end);
     130                if ((pointer->type != NULL) && (pointer->type->Z != 1))
     131                        NoNonHydrogen++;
     132                AtomCount++;
     133                return walker;
     134        } else
     135                return NULL;
    136136};
    137137
     
    141141 * -# Single Bond: Simply add new atom with bond distance rescaled to typical hydrogen one
    142142 * -# Double Bond: Here, we need the **BondList of the \a *origin atom, by scanning for the other bonds instead of
    143  *    *Bond, we use the through these connected atoms to determine the plane they lie in, vector::MakeNormalvector().
    144  *    The orthonormal vector to this plane along with the vector in *Bond direction determines the plane the two
    145  *    replacing hydrogens shall lie in. Now, all remains to do is take the usual hydrogen double bond angle for the
    146  *    element of *origin and form the sin/cos admixture of both plane vectors for the new coordinates of the two
    147  *    hydrogens forming this angle with *origin.
     143 *              *Bond, we use the through these connected atoms to determine the plane they lie in, vector::MakeNormalvector().
     144 *              The orthonormal vector to this plane along with the vector in *Bond direction determines the plane the two
     145 *              replacing hydrogens shall lie in. Now, all remains to do is take the usual hydrogen double bond angle for the
     146 *              element of *origin and form the sin/cos admixture of both plane vectors for the new coordinates of the two
     147 *              hydrogens forming this angle with *origin.
    148148 * -# 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
    149  *    triangle formed by the to be added hydrogens are not equal to the typical bond distance \f$l\f$ but have to be
    150  *    determined from the typical angle \f$\alpha\f$ for a hydrogen triple connected to the element of *origin):
    151  *    We have the height \f$d\f$ as the vector in *Bond direction (from triangle C1-H1-H2).
    152  *    \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 )}}
    153  *    \f]
    154  *    vector::GetNormalvector() creates one orthonormal vector from this *Bond vector and vector::MakeNormalvector creates
    155  *    the third one from the former two vectors. The latter ones form the plane of the base triangle mentioned above.
    156  *    The lengths for these are \f$f\f$ and \f$g\f$ (from triangle H1-H2-(center of H1-H2-H3)) with knowledge that
    157  *    the median lines in an isosceles triangle meet in the center point with a ratio 2:1.
    158  *    \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2}
    159  *    \f]
    160  *    as the coordination of all three atoms in the coordinate system of these three vectors:
    161  *    \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$.
     149 *              triangle formed by the to be added hydrogens are not equal to the typical bond distance \f$l\f$ but have to be
     150 *              determined from the typical angle \f$\alpha\f$ for a hydrogen triple connected to the element of *origin):
     151 *              We have the height \f$d\f$ as the vector in *Bond direction (from triangle C1-H1-H2).
     152 *              \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 )}}
     153 *              \f]
     154 *              vector::GetNormalvector() creates one orthonormal vector from this *Bond vector and vector::MakeNormalvector creates
     155 *              the third one from the former two vectors. The latter ones form the plane of the base triangle mentioned above.
     156 *              The lengths for these are \f$f\f$ and \f$g\f$ (from triangle H1-H2-(center of H1-H2-H3)) with knowledge that
     157 *              the median lines in an isosceles triangle meet in the center point with a ratio 2:1.
     158 *              \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2}
     159 *              \f]
     160 *              as the coordination of all three atoms in the coordinate system of these three vectors:
     161 *              \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$.
    162162 *
    163163 * \param *out output stream for debugging
     
    167167 * \param *replacement pointer to the atom which shall be copied as a hydrogen atom in this molecule
    168168 * \param **BondList list of bonds \a *replacement has (necessary to determine plane for double and triple bonds)
    169  * \param NumBond  number of bonds in \a **BondList
     169 * \param NumBond       number of bonds in \a **BondList
    170170 * \param isAngstroem whether the coordination of the given atoms is in AtomicLength (false) or Angstrom(true)
    171171 * \return number of atoms added, if < bond::BondDegree then something went wrong
     
    174174bool molecule::AddHydrogenReplacementAtom(ofstream *out, bond *TopBond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem)
    175175{
    176   double bondlength;  // bond length of the bond to be replaced/cut
    177   double bondangle;  // bond angle of the bond to be replaced/cut
    178   double BondRescale;  // rescale value for the hydrogen bond length
    179   bool AllWentWell = true;    // flag gathering the boolean return value of molecule::AddAtom and other functions, as return value on exit
    180   bond *FirstBond = NULL, *SecondBond = NULL; // Other bonds in double bond case to determine "other" plane
    181   atom *FirstOtherAtom = NULL, *SecondOtherAtom = NULL, *ThirdOtherAtom = NULL; // pointer to hydrogen atoms to be added
    182   double b,l,d,f,g, alpha, factors[NDIM];    // hold temporary values in triple bond case for coordination determination
    183   Vector Orthovector1, Orthovector2;  // temporary vectors in coordination construction
    184   Vector InBondvector;    // vector in direction of *Bond
    185   bond *Binder = NULL;
    186   double *matrix;
     176        double bondlength;      // bond length of the bond to be replaced/cut
     177        double bondangle;       // bond angle of the bond to be replaced/cut
     178        double BondRescale;      // rescale value for the hydrogen bond length
     179        bool AllWentWell = true;                // flag gathering the boolean return value of molecule::AddAtom and other functions, as return value on exit
     180        bond *FirstBond = NULL, *SecondBond = NULL; // Other bonds in double bond case to determine "other" plane
     181        atom *FirstOtherAtom = NULL, *SecondOtherAtom = NULL, *ThirdOtherAtom = NULL; // pointer to hydrogen atoms to be added
     182        double b,l,d,f,g, alpha, factors[NDIM];         // hold temporary values in triple bond case for coordination determination
     183        Vector Orthovector1, Orthovector2;      // temporary vectors in coordination construction
     184        Vector InBondvector;            // vector in direction of *Bond
     185        bond *Binder = NULL;
     186        double *matrix;
    187187
    188188//      *out << Verbose(3) << "Begin of AddHydrogenReplacementAtom." << endl;
    189   // create vector in direction of bond
    190   InBondvector.CopyVector(&TopReplacement->x);
    191   InBondvector.SubtractVector(&TopOrigin->x);
    192   bondlength = InBondvector.Norm();
    193 
    194   // is greater than typical bond distance? Then we have to correct periodically
    195   // the problem is not the H being out of the box, but InBondvector have the wrong direction
    196   // due to TopReplacement or Origin being on the wrong side!
    197   if (bondlength > BondDistance) {
    198 //    *out << Verbose(4) << "InBondvector is: ";
    199 //    InBondvector.Output(out);
    200 //    *out << endl;
    201     Orthovector1.Zero();
    202     for (int i=NDIM;i--;) {
    203       l = TopReplacement->x.x[i] - TopOrigin->x.x[i];
    204       if (fabs(l) > BondDistance) { // is component greater than bond distance
    205         Orthovector1.x[i] = (l < 0) ? -1. : +1.;
    206       } // (signs are correct, was tested!)
    207     }
    208     matrix = ReturnFullMatrixforSymmetric(cell_size);
    209     Orthovector1.MatrixMultiplication(matrix);
    210     InBondvector.SubtractVector(&Orthovector1); // subtract just the additional translation
    211     Free((void **)&matrix, "molecule::AddHydrogenReplacementAtom: *matrix");
    212     bondlength = InBondvector.Norm();
    213 //    *out << Verbose(4) << "Corrected InBondvector is now: ";
    214 //    InBondvector.Output(out);
    215 //    *out << endl;
    216   } // periodic correction finished
    217 
    218   InBondvector.Normalize();
    219   // get typical bond length and store as scale factor for later
    220   BondRescale = TopOrigin->type->HBondDistance[TopBond->BondDegree-1];
    221   if (BondRescale == -1) {
    222     cerr << Verbose(3) << "ERROR: There is no typical hydrogen bond distance in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl;
    223     return false;
    224     BondRescale = bondlength;
    225   } else {
    226     if (!IsAngstroem)
    227       BondRescale /= (1.*AtomicLengthToAngstroem);
    228   }
    229 
    230   // discern single, double and triple bonds
    231   switch(TopBond->BondDegree) {
    232     case 1:
    233       FirstOtherAtom = new atom();    // new atom
    234       FirstOtherAtom->type = elemente->FindElement(1);  // element is Hydrogen
    235       FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
    236       FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
    237       if (TopReplacement->type->Z == 1) { // neither rescale nor replace if it's already hydrogen
    238         FirstOtherAtom->father = TopReplacement;
    239         BondRescale = bondlength;
    240       } else {
    241         FirstOtherAtom->father = NULL;  // if we replace hydrogen, we mark it as our father, otherwise we are just an added hydrogen with no father
    242       }
    243       InBondvector.Scale(&BondRescale);  // rescale the distance vector to Hydrogen bond length
    244       FirstOtherAtom->x.CopyVector(&TopOrigin->x); // set coordination to origin ...
    245       FirstOtherAtom->x.AddVector(&InBondvector);  // ... and add distance vector to replacement atom
    246       AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
    247 //      *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
    248 //      FirstOtherAtom->x.Output(out);
    249 //      *out << endl;
    250       Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);
    251       Binder->Cyclic = false;
    252       Binder->Type = TreeEdge;
    253       break;
    254     case 2:
    255       // determine two other bonds (warning if there are more than two other) plus valence sanity check
    256       for (int i=0;i<NumBond;i++) {
    257         if (BondList[i] != TopBond) {
    258           if (FirstBond == NULL) {
    259             FirstBond = BondList[i];
    260             FirstOtherAtom = BondList[i]->GetOtherAtom(TopOrigin);
    261           } else if (SecondBond == NULL) {
    262             SecondBond = BondList[i];
    263             SecondOtherAtom = BondList[i]->GetOtherAtom(TopOrigin);
    264           } else {
    265             *out << Verbose(3) << "WARNING: Detected more than four bonds for atom " << TopOrigin->Name;
    266           }
    267         }
    268       }
    269       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)
    270         SecondBond = TopBond;
    271         SecondOtherAtom = TopReplacement;
    272       }
    273       if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all
    274 //        *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;
    275 
    276         // determine the plane of these two with the *origin
    277         AllWentWell = AllWentWell && Orthovector1.MakeNormalVector(&TopOrigin->x, &FirstOtherAtom->x, &SecondOtherAtom->x);
    278       } else {
    279         Orthovector1.GetOneNormalVector(&InBondvector);
    280       }
    281       //*out << Verbose(3)<< "Orthovector1: ";
    282       //Orthovector1.Output(out);
    283       //*out << endl;
    284       // orthogonal vector and bond vector between origin and replacement form the new plane
    285       Orthovector1.MakeNormalVector(&InBondvector);
    286       Orthovector1.Normalize();
    287       //*out << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl;
    288 
    289       // create the two Hydrogens ...
    290       FirstOtherAtom = new atom();
    291       SecondOtherAtom = new atom();
    292       FirstOtherAtom->type = elemente->FindElement(1);
    293       SecondOtherAtom->type = elemente->FindElement(1);
    294       FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
    295       FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
    296       SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
    297       SecondOtherAtom->FixedIon = TopReplacement->FixedIon;
    298       FirstOtherAtom->father = NULL;  // we are just an added hydrogen with no father
    299       SecondOtherAtom->father = NULL;  //  we are just an added hydrogen with no father
    300       bondangle = TopOrigin->type->HBondAngle[1];
    301       if (bondangle == -1) {
    302         *out << Verbose(3) << "ERROR: There is no typical hydrogen bond angle in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl;
    303         return false;
    304         bondangle = 0;
    305       }
    306       bondangle *= M_PI/180./2.;
    307 //      *out << Verbose(3) << "ReScaleCheck: InBondvector ";
    308 //      InBondvector.Output(out);
    309 //      *out << endl;
    310 //      *out << Verbose(3) << "ReScaleCheck: Orthovector ";
    311 //      Orthovector1.Output(out);
    312 //      *out << endl;
    313 //      *out << Verbose(3) << "Half the bond angle is " << bondangle << ", sin and cos of it: " << sin(bondangle) << ", " << cos(bondangle) << endl;
    314       FirstOtherAtom->x.Zero();
    315       SecondOtherAtom->x.Zero();
    316       for(int i=NDIM;i--;) { // rotate by half the bond angle in both directions (InBondvector is bondangle = 0 direction)
    317         FirstOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (sin(bondangle));
    318         SecondOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (-sin(bondangle));
    319       }
    320       FirstOtherAtom->x.Scale(&BondRescale);  // rescale by correct BondDistance
    321       SecondOtherAtom->x.Scale(&BondRescale);
    322       //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl;
    323       for(int i=NDIM;i--;) { // and make relative to origin atom
    324         FirstOtherAtom->x.x[i] += TopOrigin->x.x[i];
    325         SecondOtherAtom->x.x[i] += TopOrigin->x.x[i];
    326       }
    327       // ... and add to molecule
    328       AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
    329       AllWentWell = AllWentWell && AddAtom(SecondOtherAtom);
    330 //      *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
    331 //      FirstOtherAtom->x.Output(out);
    332 //      *out << endl;
    333 //      *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: ";
    334 //      SecondOtherAtom->x.Output(out);
    335 //      *out << endl;
    336       Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);
    337       Binder->Cyclic = false;
    338       Binder->Type = TreeEdge;
    339       Binder = AddBond(BottomOrigin, SecondOtherAtom, 1);
    340       Binder->Cyclic = false;
    341       Binder->Type = TreeEdge;
    342       break;
    343     case 3:
    344       // take the "usual" tetraoidal angle and add the three Hydrogen in direction of the bond (height of the tetraoid)
    345       FirstOtherAtom = new atom();
    346       SecondOtherAtom = new atom();
    347       ThirdOtherAtom = new atom();
    348       FirstOtherAtom->type = elemente->FindElement(1);
    349       SecondOtherAtom->type = elemente->FindElement(1);
    350       ThirdOtherAtom->type = elemente->FindElement(1);
    351       FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
    352       FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
    353       SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
    354       SecondOtherAtom->FixedIon = TopReplacement->FixedIon;
    355       ThirdOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
    356       ThirdOtherAtom->FixedIon = TopReplacement->FixedIon;
    357       FirstOtherAtom->father = NULL;  //  we are just an added hydrogen with no father
    358       SecondOtherAtom->father = NULL;  //  we are just an added hydrogen with no father
    359       ThirdOtherAtom->father = NULL;  //  we are just an added hydrogen with no father
    360 
    361       // we need to vectors orthonormal the InBondvector
    362       AllWentWell = AllWentWell && Orthovector1.GetOneNormalVector(&InBondvector);
    363 //      *out << Verbose(3) << "Orthovector1: ";
    364 //      Orthovector1.Output(out);
    365 //      *out << endl;
    366       AllWentWell = AllWentWell && Orthovector2.MakeNormalVector(&InBondvector, &Orthovector1);
    367 //      *out << Verbose(3) << "Orthovector2: ";
    368 //      Orthovector2.Output(out);
    369 //      *out << endl;
    370 
    371       // create correct coordination for the three atoms
    372       alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.;  // retrieve triple bond angle from database
    373       l = BondRescale;        // desired bond length
    374       b = 2.*l*sin(alpha);    // base length of isosceles triangle
    375       d = l*sqrt(cos(alpha)*cos(alpha) - sin(alpha)*sin(alpha)/3.);  // length for InBondvector
    376       f = b/sqrt(3.);  // length for Orthvector1
    377       g = b/2.;        // length for Orthvector2
    378 //      *out << Verbose(3) << "Bond length and half-angle: " << l << ", " << alpha << "\t (b,d,f,g) = " << b << ", " << d << ", " << f << ", " << g << ", " << endl;
    379 //      *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;
    380       factors[0] = d;
    381       factors[1] = f;
    382       factors[2] = 0.;
    383       FirstOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);
    384       factors[1] = -0.5*f;
    385       factors[2] = g;
    386       SecondOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);
    387       factors[2] = -g;
    388       ThirdOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);
    389 
    390       // rescale each to correct BondDistance
    391 //      FirstOtherAtom->x.Scale(&BondRescale);
    392 //      SecondOtherAtom->x.Scale(&BondRescale);
    393 //      ThirdOtherAtom->x.Scale(&BondRescale);
    394 
    395       // and relative to *origin atom
    396       FirstOtherAtom->x.AddVector(&TopOrigin->x);
    397       SecondOtherAtom->x.AddVector(&TopOrigin->x);
    398       ThirdOtherAtom->x.AddVector(&TopOrigin->x);
    399 
    400       // ... and add to molecule
    401       AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
    402       AllWentWell = AllWentWell && AddAtom(SecondOtherAtom);
    403       AllWentWell = AllWentWell && AddAtom(ThirdOtherAtom);
    404 //      *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
    405 //      FirstOtherAtom->x.Output(out);
    406 //      *out << endl;
    407 //      *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: ";
    408 //      SecondOtherAtom->x.Output(out);
    409 //      *out << endl;
    410 //      *out << Verbose(4) << "Added " << *ThirdOtherAtom << " at: ";
    411 //      ThirdOtherAtom->x.Output(out);
    412 //      *out << endl;
    413       Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);
    414       Binder->Cyclic = false;
    415       Binder->Type = TreeEdge;
    416       Binder = AddBond(BottomOrigin, SecondOtherAtom, 1);
    417       Binder->Cyclic = false;
    418       Binder->Type = TreeEdge;
    419       Binder = AddBond(BottomOrigin, ThirdOtherAtom, 1);
    420       Binder->Cyclic = false;
    421       Binder->Type = TreeEdge;
    422       break;
    423     default:
    424       cerr << "ERROR: BondDegree does not state single, double or triple bond!" << endl;
    425       AllWentWell = false;
    426       break;
    427   }
     189        // create vector in direction of bond
     190        InBondvector.CopyVector(&TopReplacement->x);
     191        InBondvector.SubtractVector(&TopOrigin->x);
     192        bondlength = InBondvector.Norm();
     193
     194        // is greater than typical bond distance? Then we have to correct periodically
     195        // the problem is not the H being out of the box, but InBondvector have the wrong direction
     196        // due to TopReplacement or Origin being on the wrong side!
     197        if (bondlength > BondDistance) {
     198//              *out << Verbose(4) << "InBondvector is: ";
     199//              InBondvector.Output(out);
     200//              *out << endl;
     201                Orthovector1.Zero();
     202                for (int i=NDIM;i--;) {
     203                        l = TopReplacement->x.x[i] - TopOrigin->x.x[i];
     204                        if (fabs(l) > BondDistance) { // is component greater than bond distance
     205                                Orthovector1.x[i] = (l < 0) ? -1. : +1.;
     206                        } // (signs are correct, was tested!)
     207                }
     208                matrix = ReturnFullMatrixforSymmetric(cell_size);
     209                Orthovector1.MatrixMultiplication(matrix);
     210                InBondvector.SubtractVector(&Orthovector1); // subtract just the additional translation
     211                Free((void **)&matrix, "molecule::AddHydrogenReplacementAtom: *matrix");
     212                bondlength = InBondvector.Norm();
     213//              *out << Verbose(4) << "Corrected InBondvector is now: ";
     214//              InBondvector.Output(out);
     215//              *out << endl;
     216        } // periodic correction finished
     217
     218        InBondvector.Normalize();
     219        // get typical bond length and store as scale factor for later
     220        BondRescale = TopOrigin->type->HBondDistance[TopBond->BondDegree-1];
     221        if (BondRescale == -1) {
     222                cerr << Verbose(3) << "ERROR: There is no typical hydrogen bond distance in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl;
     223                return false;
     224                BondRescale = bondlength;
     225        } else {
     226                if (!IsAngstroem)
     227                        BondRescale /= (1.*AtomicLengthToAngstroem);
     228        }
     229
     230        // discern single, double and triple bonds
     231        switch(TopBond->BondDegree) {
     232                case 1:
     233                        FirstOtherAtom = new atom();            // new atom
     234                        FirstOtherAtom->type = elemente->FindElement(1);        // element is Hydrogen
     235                        FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
     236                        FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
     237                        if (TopReplacement->type->Z == 1) { // neither rescale nor replace if it's already hydrogen
     238                                FirstOtherAtom->father = TopReplacement;
     239                                BondRescale = bondlength;
     240                        } else {
     241                                FirstOtherAtom->father = NULL;  // if we replace hydrogen, we mark it as our father, otherwise we are just an added hydrogen with no father
     242                        }
     243                        InBondvector.Scale(&BondRescale);        // rescale the distance vector to Hydrogen bond length
     244                        FirstOtherAtom->x.CopyVector(&TopOrigin->x); // set coordination to origin ...
     245                        FirstOtherAtom->x.AddVector(&InBondvector);     // ... and add distance vector to replacement atom
     246                        AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
     247//                      *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
     248//                      FirstOtherAtom->x.Output(out);
     249//                      *out << endl;
     250                        Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);
     251                        Binder->Cyclic = false;
     252                        Binder->Type = TreeEdge;
     253                        break;
     254                case 2:
     255                        // determine two other bonds (warning if there are more than two other) plus valence sanity check
     256                        for (int i=0;i<NumBond;i++) {
     257                                if (BondList[i] != TopBond) {
     258                                        if (FirstBond == NULL) {
     259                                                FirstBond = BondList[i];
     260                                                FirstOtherAtom = BondList[i]->GetOtherAtom(TopOrigin);
     261                                        } else if (SecondBond == NULL) {
     262                                                SecondBond = BondList[i];
     263                                                SecondOtherAtom = BondList[i]->GetOtherAtom(TopOrigin);
     264                                        } else {
     265                                                *out << Verbose(3) << "WARNING: Detected more than four bonds for atom " << TopOrigin->Name;
     266                                        }
     267                                }
     268                        }
     269                        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)
     270                                SecondBond = TopBond;
     271                                SecondOtherAtom = TopReplacement;
     272                        }
     273                        if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all
     274//                              *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;
     275
     276                                // determine the plane of these two with the *origin
     277                                AllWentWell = AllWentWell && Orthovector1.MakeNormalVector(&TopOrigin->x, &FirstOtherAtom->x, &SecondOtherAtom->x);
     278                        } else {
     279                                Orthovector1.GetOneNormalVector(&InBondvector);
     280                        }
     281                        //*out << Verbose(3)<< "Orthovector1: ";
     282                        //Orthovector1.Output(out);
     283                        //*out << endl;
     284                        // orthogonal vector and bond vector between origin and replacement form the new plane
     285                        Orthovector1.MakeNormalVector(&InBondvector);
     286                        Orthovector1.Normalize();
     287                        //*out << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl;
     288
     289                        // create the two Hydrogens ...
     290                        FirstOtherAtom = new atom();
     291                        SecondOtherAtom = new atom();
     292                        FirstOtherAtom->type = elemente->FindElement(1);
     293                        SecondOtherAtom->type = elemente->FindElement(1);
     294                        FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
     295                        FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
     296                        SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
     297                        SecondOtherAtom->FixedIon = TopReplacement->FixedIon;
     298                        FirstOtherAtom->father = NULL;  // we are just an added hydrogen with no father
     299                        SecondOtherAtom->father = NULL; //      we are just an added hydrogen with no father
     300                        bondangle = TopOrigin->type->HBondAngle[1];
     301                        if (bondangle == -1) {
     302                                *out << Verbose(3) << "ERROR: There is no typical hydrogen bond angle in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl;
     303                                return false;
     304                                bondangle = 0;
     305                        }
     306                        bondangle *= M_PI/180./2.;
     307//                      *out << Verbose(3) << "ReScaleCheck: InBondvector ";
     308//                      InBondvector.Output(out);
     309//                      *out << endl;
     310//                      *out << Verbose(3) << "ReScaleCheck: Orthovector ";
     311//                      Orthovector1.Output(out);
     312//                      *out << endl;
     313//                      *out << Verbose(3) << "Half the bond angle is " << bondangle << ", sin and cos of it: " << sin(bondangle) << ", " << cos(bondangle) << endl;
     314                        FirstOtherAtom->x.Zero();
     315                        SecondOtherAtom->x.Zero();
     316                        for(int i=NDIM;i--;) { // rotate by half the bond angle in both directions (InBondvector is bondangle = 0 direction)
     317                                FirstOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (sin(bondangle));
     318                                SecondOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (-sin(bondangle));
     319                        }
     320                        FirstOtherAtom->x.Scale(&BondRescale);  // rescale by correct BondDistance
     321                        SecondOtherAtom->x.Scale(&BondRescale);
     322                        //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl;
     323                        for(int i=NDIM;i--;) { // and make relative to origin atom
     324                                FirstOtherAtom->x.x[i] += TopOrigin->x.x[i];
     325                                SecondOtherAtom->x.x[i] += TopOrigin->x.x[i];
     326                        }
     327                        // ... and add to molecule
     328                        AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
     329                        AllWentWell = AllWentWell && AddAtom(SecondOtherAtom);
     330//                      *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
     331//                      FirstOtherAtom->x.Output(out);
     332//                      *out << endl;
     333//                      *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: ";
     334//                      SecondOtherAtom->x.Output(out);
     335//                      *out << endl;
     336                        Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);
     337                        Binder->Cyclic = false;
     338                        Binder->Type = TreeEdge;
     339                        Binder = AddBond(BottomOrigin, SecondOtherAtom, 1);
     340                        Binder->Cyclic = false;
     341                        Binder->Type = TreeEdge;
     342                        break;
     343                case 3:
     344                        // take the "usual" tetraoidal angle and add the three Hydrogen in direction of the bond (height of the tetraoid)
     345                        FirstOtherAtom = new atom();
     346                        SecondOtherAtom = new atom();
     347                        ThirdOtherAtom = new atom();
     348                        FirstOtherAtom->type = elemente->FindElement(1);
     349                        SecondOtherAtom->type = elemente->FindElement(1);
     350                        ThirdOtherAtom->type = elemente->FindElement(1);
     351                        FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
     352                        FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
     353                        SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
     354                        SecondOtherAtom->FixedIon = TopReplacement->FixedIon;
     355                        ThirdOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
     356                        ThirdOtherAtom->FixedIon = TopReplacement->FixedIon;
     357                        FirstOtherAtom->father = NULL;  //      we are just an added hydrogen with no father
     358                        SecondOtherAtom->father = NULL; //      we are just an added hydrogen with no father
     359                        ThirdOtherAtom->father = NULL;  //      we are just an added hydrogen with no father
     360
     361                        // we need to vectors orthonormal the InBondvector
     362                        AllWentWell = AllWentWell && Orthovector1.GetOneNormalVector(&InBondvector);
     363//                      *out << Verbose(3) << "Orthovector1: ";
     364//                      Orthovector1.Output(out);
     365//                      *out << endl;
     366                        AllWentWell = AllWentWell && Orthovector2.MakeNormalVector(&InBondvector, &Orthovector1);
     367//                      *out << Verbose(3) << "Orthovector2: ";
     368//                      Orthovector2.Output(out);
     369//                      *out << endl;
     370
     371                        // create correct coordination for the three atoms
     372                        alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.;  // retrieve triple bond angle from database
     373                        l = BondRescale;                                // desired bond length
     374                        b = 2.*l*sin(alpha);            // base length of isosceles triangle
     375                        d = l*sqrt(cos(alpha)*cos(alpha) - sin(alpha)*sin(alpha)/3.);    // length for InBondvector
     376                        f = b/sqrt(3.); // length for Orthvector1
     377                        g = b/2.;                                // length for Orthvector2
     378//                      *out << Verbose(3) << "Bond length and half-angle: " << l << ", " << alpha << "\t (b,d,f,g) = " << b << ", " << d << ", " << f << ", " << g << ", " << endl;
     379//                      *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;
     380                        factors[0] = d;
     381                        factors[1] = f;
     382                        factors[2] = 0.;
     383                        FirstOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);
     384                        factors[1] = -0.5*f;
     385                        factors[2] = g;
     386                        SecondOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);
     387                        factors[2] = -g;
     388                        ThirdOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);
     389
     390                        // rescale each to correct BondDistance
     391//                      FirstOtherAtom->x.Scale(&BondRescale);
     392//                      SecondOtherAtom->x.Scale(&BondRescale);
     393//                      ThirdOtherAtom->x.Scale(&BondRescale);
     394
     395                        // and relative to *origin atom
     396                        FirstOtherAtom->x.AddVector(&TopOrigin->x);
     397                        SecondOtherAtom->x.AddVector(&TopOrigin->x);
     398                        ThirdOtherAtom->x.AddVector(&TopOrigin->x);
     399
     400                        // ... and add to molecule
     401                        AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
     402                        AllWentWell = AllWentWell && AddAtom(SecondOtherAtom);
     403                        AllWentWell = AllWentWell && AddAtom(ThirdOtherAtom);
     404//                      *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
     405//                      FirstOtherAtom->x.Output(out);
     406//                      *out << endl;
     407//                      *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: ";
     408//                      SecondOtherAtom->x.Output(out);
     409//                      *out << endl;
     410//                      *out << Verbose(4) << "Added " << *ThirdOtherAtom << " at: ";
     411//                      ThirdOtherAtom->x.Output(out);
     412//                      *out << endl;
     413                        Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);
     414                        Binder->Cyclic = false;
     415                        Binder->Type = TreeEdge;
     416                        Binder = AddBond(BottomOrigin, SecondOtherAtom, 1);
     417                        Binder->Cyclic = false;
     418                        Binder->Type = TreeEdge;
     419                        Binder = AddBond(BottomOrigin, ThirdOtherAtom, 1);
     420                        Binder->Cyclic = false;
     421                        Binder->Type = TreeEdge;
     422                        break;
     423                default:
     424                        cerr << "ERROR: BondDegree does not state single, double or triple bond!" << endl;
     425                        AllWentWell = false;
     426                        break;
     427        }
    428428
    429429//      *out << Verbose(3) << "End of AddHydrogenReplacementAtom." << endl;
    430   return AllWentWell;
     430        return AllWentWell;
    431431};
    432432
     
    438438bool molecule::AddXYZFile(string filename)
    439439{
    440   istringstream *input = NULL;
    441   int NumberOfAtoms = 0; // atom number in xyz read
    442   int i, j; // loop variables
    443   atom *Walker = NULL;  // pointer to added atom
    444   char shorthand[3];  // shorthand for atom name
    445   ifstream xyzfile;  // xyz file
    446   string line;    // currently parsed line
    447   double x[3];    // atom coordinates
    448 
    449   xyzfile.open(filename.c_str());
    450   if (!xyzfile)
    451     return false;
    452 
    453   getline(xyzfile,line,'\n'); // Read numer of atoms in file
    454   input = new istringstream(line);
    455   *input >> NumberOfAtoms;
    456   cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl;
    457   getline(xyzfile,line,'\n'); // Read comment
    458   cout << Verbose(1) << "Comment: " << line << endl;
    459 
    460   if (MDSteps == 0) // no atoms yet present
    461     MDSteps++;
    462   for(i=0;i<NumberOfAtoms;i++){
    463     Walker = new atom;
    464     getline(xyzfile,line,'\n');
    465     istringstream *item = new istringstream(line);
    466     //istringstream input(line);
    467     //cout << Verbose(1) << "Reading: " << line << endl;
    468     *item >> shorthand;
    469     *item >> x[0];
    470     *item >> x[1];
    471     *item >> x[2];
    472     Walker->type = elemente->FindElement(shorthand);
    473     if (Walker->type == NULL) {
    474       cerr << "Could not parse the element at line: '" << line << "', setting to H.";
    475       Walker->type = elemente->FindElement(1);
    476     }
    477     if (Trajectories[Walker].R.size() <= (unsigned int)MDSteps) {
    478       Trajectories[Walker].R.resize(MDSteps+10);
    479       Trajectories[Walker].U.resize(MDSteps+10);
    480       Trajectories[Walker].F.resize(MDSteps+10);
    481     }
    482     for(j=NDIM;j--;) {
    483       Walker->x.x[j] = x[j];
    484       Trajectories[Walker].R.at(MDSteps-1).x[j] = x[j];
    485       Trajectories[Walker].U.at(MDSteps-1).x[j] = 0;
    486       Trajectories[Walker].F.at(MDSteps-1).x[j] = 0;
    487     }
    488     AddAtom(Walker);  // add to molecule
    489     delete(item);
    490   }
    491   xyzfile.close();
    492   delete(input);
    493   return true;
     440        istringstream *input = NULL;
     441        int NumberOfAtoms = 0; // atom number in xyz read
     442        int i, j; // loop variables
     443        atom *Walker = NULL;    // pointer to added atom
     444        char shorthand[3];      // shorthand for atom name
     445        ifstream xyzfile;        // xyz file
     446        string line;            // currently parsed line
     447        double x[3];            // atom coordinates
     448
     449        xyzfile.open(filename.c_str());
     450        if (!xyzfile)
     451                return false;
     452
     453        getline(xyzfile,line,'\n'); // Read numer of atoms in file
     454        input = new istringstream(line);
     455        *input >> NumberOfAtoms;
     456        cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl;
     457        getline(xyzfile,line,'\n'); // Read comment
     458        cout << Verbose(1) << "Comment: " << line << endl;
     459
     460        if (MDSteps == 0) // no atoms yet present
     461                MDSteps++;
     462        for(i=0;i<NumberOfAtoms;i++){
     463                Walker = new atom;
     464                getline(xyzfile,line,'\n');
     465                istringstream *item = new istringstream(line);
     466                //istringstream input(line);
     467                //cout << Verbose(1) << "Reading: " << line << endl;
     468                *item >> shorthand;
     469                *item >> x[0];
     470                *item >> x[1];
     471                *item >> x[2];
     472                Walker->type = elemente->FindElement(shorthand);
     473                if (Walker->type == NULL) {
     474                        cerr << "Could not parse the element at line: '" << line << "', setting to H.";
     475                        Walker->type = elemente->FindElement(1);
     476                }
     477                if (Trajectories[Walker].R.size() <= (unsigned int)MDSteps) {
     478                        Trajectories[Walker].R.resize(MDSteps+10);
     479                        Trajectories[Walker].U.resize(MDSteps+10);
     480                        Trajectories[Walker].F.resize(MDSteps+10);
     481                }
     482                for(j=NDIM;j--;) {
     483                        Walker->x.x[j] = x[j];
     484                        Trajectories[Walker].R.at(MDSteps-1).x[j] = x[j];
     485                        Trajectories[Walker].U.at(MDSteps-1).x[j] = 0;
     486                        Trajectories[Walker].F.at(MDSteps-1).x[j] = 0;
     487                }
     488                AddAtom(Walker);        // add to molecule
     489                delete(item);
     490        }
     491        xyzfile.close();
     492        delete(input);
     493        return true;
    494494};
    495495
     
    499499molecule *molecule::CopyMolecule()
    500500{
    501   molecule *copy = new molecule(elemente);
    502   atom *CurrentAtom = NULL;
    503   atom *LeftAtom = NULL, *RightAtom = NULL;
    504   atom *Walker = NULL;
    505 
    506   // copy all atoms
    507   Walker = start;
    508   while(Walker->next != end) {
    509     Walker = Walker->next;
    510     CurrentAtom = copy->AddCopyAtom(Walker);
    511   }
    512 
    513   // copy all bonds
    514   bond *Binder = first;
    515   bond *NewBond = NULL;
    516   while(Binder->next != last) {
    517     Binder = Binder->next;
    518     // get the pendant atoms of current bond in the copy molecule
    519     LeftAtom = copy->start;
    520     while (LeftAtom->next != copy->end) {
    521       LeftAtom = LeftAtom->next;
    522       if (LeftAtom->father == Binder->leftatom)
    523         break;
    524     }
    525     RightAtom = copy->start;
    526     while (RightAtom->next != copy->end) {
    527       RightAtom = RightAtom->next;
    528       if (RightAtom->father == Binder->rightatom)
    529         break;
    530     }
    531     NewBond = copy->AddBond(LeftAtom, RightAtom, Binder->BondDegree);
    532     NewBond->Cyclic = Binder->Cyclic;
    533     if (Binder->Cyclic)
    534       copy->NoCyclicBonds++;
    535     NewBond->Type = Binder->Type;
    536   }
    537   // correct fathers
    538   Walker = copy->start;
    539   while(Walker->next != copy->end) {
    540     Walker = Walker->next;
    541     if (Walker->father->father == Walker->father)  // same atom in copy's father points to itself
    542       Walker->father = Walker;  // set father to itself (copy of a whole molecule)
    543     else
    544      Walker->father = Walker->father->father;  // set father to original's father
    545   }
    546   // copy values
    547   copy->CountAtoms((ofstream *)&cout);
    548   copy->CountElements();
    549   if (first->next != last) {  // if adjaceny list is present
    550     copy->BondDistance = BondDistance;
    551     copy->CreateListOfBondsPerAtom((ofstream *)&cout);
    552   }
    553 
    554   return copy;
     501        molecule *copy = new molecule(elemente);
     502        atom *CurrentAtom = NULL;
     503        atom *LeftAtom = NULL, *RightAtom = NULL;
     504        atom *Walker = NULL;
     505
     506        // copy all atoms
     507        Walker = start;
     508        while(Walker->next != end) {
     509                Walker = Walker->next;
     510                CurrentAtom = copy->AddCopyAtom(Walker);
     511        }
     512
     513        // copy all bonds
     514        bond *Binder = first;
     515        bond *NewBond = NULL;
     516        while(Binder->next != last) {
     517                Binder = Binder->next;
     518                // get the pendant atoms of current bond in the copy molecule
     519                LeftAtom = copy->start;
     520                while (LeftAtom->next != copy->end) {
     521                        LeftAtom = LeftAtom->next;
     522                        if (LeftAtom->father == Binder->leftatom)
     523                                break;
     524                }
     525                RightAtom = copy->start;
     526                while (RightAtom->next != copy->end) {
     527                        RightAtom = RightAtom->next;
     528                        if (RightAtom->father == Binder->rightatom)
     529                                break;
     530                }
     531                NewBond = copy->AddBond(LeftAtom, RightAtom, Binder->BondDegree);
     532                NewBond->Cyclic = Binder->Cyclic;
     533                if (Binder->Cyclic)
     534                        copy->NoCyclicBonds++;
     535                NewBond->Type = Binder->Type;
     536        }
     537        // correct fathers
     538        Walker = copy->start;
     539        while(Walker->next != copy->end) {
     540                Walker = Walker->next;
     541                if (Walker->father->father == Walker->father)    // same atom in copy's father points to itself
     542                        Walker->father = Walker;        // set father to itself (copy of a whole molecule)
     543                else
     544                 Walker->father = Walker->father->father;       // set father to original's father
     545        }
     546        // copy values
     547        copy->CountAtoms((ofstream *)&cout);
     548        copy->CountElements();
     549        if (first->next != last) {      // if adjaceny list is present
     550                copy->BondDistance = BondDistance;
     551                copy->CreateListOfBondsPerAtom((ofstream *)&cout);
     552        }
     553
     554        return copy;
    555555};
    556556
     
    563563bond * molecule::AddBond(atom *atom1, atom *atom2, int degree=1)
    564564{
    565   bond *Binder = NULL;
    566   if ((atom1 != NULL) && (FindAtom(atom1->nr) != NULL) && (atom2 != NULL) && (FindAtom(atom2->nr) != NULL)) {
    567     Binder = new bond(atom1, atom2, degree, BondCount++);
    568     if ((atom1->type != NULL) && (atom1->type->Z != 1) && (atom2->type != NULL) && (atom2->type->Z != 1))
    569       NoNonBonds++;
    570     add(Binder, last);
    571   } else {
    572     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;
    573   }
    574   return Binder;
     565        bond *Binder = NULL;
     566        if ((atom1 != NULL) && (FindAtom(atom1->nr) != NULL) && (atom2 != NULL) && (FindAtom(atom2->nr) != NULL)) {
     567                Binder = new bond(atom1, atom2, degree, BondCount++);
     568                if ((atom1->type != NULL) && (atom1->type->Z != 1) && (atom2->type != NULL) && (atom2->type->Z != 1))
     569                        NoNonBonds++;
     570                add(Binder, last);
     571        } else {
     572                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;
     573        }
     574        return Binder;
    575575};
    576576
     
    582582bool molecule::RemoveBond(bond *pointer)
    583583{
    584   //cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl;
    585   removewithoutcheck(pointer);
    586   return true;
     584        //cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl;
     585        removewithoutcheck(pointer);
     586        return true;
    587587};
    588588
     
    594594bool molecule::RemoveBonds(atom *BondPartner)
    595595{
    596   cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl;
    597   return false;
     596        cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl;
     597        return false;
    598598};
    599599
     
    603603void molecule::SetBoxDimension(Vector *dim)
    604604{
    605   cell_size[0] = dim->x[0];
    606   cell_size[1] = 0.;
    607   cell_size[2] = dim->x[1];
    608   cell_size[3] = 0.;
    609   cell_size[4] = 0.;
    610   cell_size[5] = dim->x[2];
     605        cell_size[0] = dim->x[0];
     606        cell_size[1] = 0.;
     607        cell_size[2] = dim->x[1];
     608        cell_size[3] = 0.;
     609        cell_size[4] = 0.;
     610        cell_size[5] = dim->x[2];
    611611};
    612612
     
    617617bool molecule::CenterInBox(ofstream *out, Vector *BoxLengths)
    618618{
    619   bool status = true;
    620   atom *ptr = NULL;
    621   Vector *min = new Vector;
    622   Vector *max = new Vector;
    623 
    624   // gather min and max for each axis
    625   ptr = start->next;  // start at first in list
    626   if (ptr != end) {  //list not empty?
    627     for (int i=NDIM;i--;) {
    628       max->x[i] = ptr->x.x[i];
    629       min->x[i] = ptr->x.x[i];
    630     }
    631     while (ptr->next != end) {  // continue with second if present
    632       ptr = ptr->next;
    633       //ptr->Output(1,1,out);
    634       for (int i=NDIM;i--;) {
    635         max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i];
    636         min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i];
    637       }
    638     }
    639   }
    640   // sanity check
    641   for(int i=NDIM;i--;) {
    642     if (max->x[i] - min->x[i] > BoxLengths->x[i])
    643       status = false;
    644   }
    645   // warn if check failed
    646   if (!status)
    647     *out << "WARNING: molecule is bigger than defined box!" << endl;
    648   else {  // else center in box
    649     max->AddVector(min);
    650     max->Scale(-1.);
    651     max->AddVector(BoxLengths);
    652     max->Scale(0.5);
    653     Translate(max);
    654   }
    655 
    656   // free and exit
    657   delete(min);
    658   delete(max);
    659   return status;
     619        bool status = true;
     620        atom *ptr = NULL;
     621        Vector *min = new Vector;
     622        Vector *max = new Vector;
     623
     624        // gather min and max for each axis
     625        ptr = start->next;      // start at first in list
     626        if (ptr != end) {        //list not empty?
     627                for (int i=NDIM;i--;) {
     628                        max->x[i] = ptr->x.x[i];
     629                        min->x[i] = ptr->x.x[i];
     630                }
     631                while (ptr->next != end) {      // continue with second if present
     632                        ptr = ptr->next;
     633                        //ptr->Output(1,1,out);
     634                        for (int i=NDIM;i--;) {
     635                                max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i];
     636                                min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i];
     637                        }
     638                }
     639        }
     640        // sanity check
     641        for(int i=NDIM;i--;) {
     642                if (max->x[i] - min->x[i] > BoxLengths->x[i])
     643                        status = false;
     644        }
     645        // warn if check failed
     646        if (!status)
     647                *out << "WARNING: molecule is bigger than defined box!" << endl;
     648        else {  // else center in box
     649                max->AddVector(min);
     650                max->Scale(-1.);
     651                max->AddVector(BoxLengths);
     652                max->Scale(0.5);
     653                Translate(max);
     654        }
     655
     656        // free and exit
     657        delete(min);
     658        delete(max);
     659        return status;
    660660};
    661661
     
    666666void molecule::CenterEdge(ofstream *out, Vector *max)
    667667{
    668   Vector *min = new Vector;
    669 
    670 //  *out << Verbose(3) << "Begin of CenterEdge." << endl;
    671   atom *ptr = start->next;  // start at first in list
    672   if (ptr != end) {  //list not empty?
    673     for (int i=NDIM;i--;) {
    674       max->x[i] = ptr->x.x[i];
    675       min->x[i] = ptr->x.x[i];
    676     }
    677     while (ptr->next != end) {  // continue with second if present
    678       ptr = ptr->next;
    679       //ptr->Output(1,1,out);
    680       for (int i=NDIM;i--;) {
    681         max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i];
    682         min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i];
    683       }
    684     }
    685 //    *out << Verbose(4) << "Maximum is ";
    686 //    max->Output(out);
    687 //    *out << ", Minimum is ";
    688 //    min->Output(out);
    689 //    *out << endl;
    690     min->Scale(-1.);
    691     max->AddVector(min);
    692     Translate(min);
    693   }
    694   delete(min);
    695 //  *out << Verbose(3) << "End of CenterEdge." << endl;
     668        Vector *min = new Vector;
     669
     670//      *out << Verbose(3) << "Begin of CenterEdge." << endl;
     671        atom *ptr = start->next;        // start at first in list
     672        if (ptr != end) {        //list not empty?
     673                for (int i=NDIM;i--;) {
     674                        max->x[i] = ptr->x.x[i];
     675                        min->x[i] = ptr->x.x[i];
     676                }
     677                while (ptr->next != end) {      // continue with second if present
     678                        ptr = ptr->next;
     679                        //ptr->Output(1,1,out);
     680                        for (int i=NDIM;i--;) {
     681                                max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i];
     682                                min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i];
     683                        }
     684                }
     685//              *out << Verbose(4) << "Maximum is ";
     686//              max->Output(out);
     687//              *out << ", Minimum is ";
     688//              min->Output(out);
     689//              *out << endl;
     690                min->Scale(-1.);
     691                max->AddVector(min);
     692                Translate(min);
     693        }
     694        delete(min);
     695//      *out << Verbose(3) << "End of CenterEdge." << endl;
    696696};
    697697
     
    702702void molecule::CenterOrigin(ofstream *out, Vector *center)
    703703{
    704   int Num = 0;
    705   atom *ptr = start->next;  // start at first in list
    706 
    707   for(int i=NDIM;i--;) // zero center vector
    708     center->x[i] = 0.;
    709 
    710   if (ptr != end) {  //list not empty?
    711     while (ptr->next != end) {  // continue with second if present
    712       ptr = ptr->next;
    713       Num++;
    714       center->AddVector(&ptr->x);
    715     }
    716     center->Scale(-1./Num); // divide through total number (and sign for direction)
    717     Translate(center);
    718   }
     704        int Num = 0;
     705        atom *ptr = start->next;        // start at first in list
     706
     707        for(int i=NDIM;i--;) // zero center vector
     708                center->x[i] = 0.;
     709
     710        if (ptr != end) {        //list not empty?
     711                while (ptr->next != end) {      // continue with second if present
     712                        ptr = ptr->next;
     713                        Num++;
     714                        center->AddVector(&ptr->x);
     715                }
     716                center->Scale(-1./Num); // divide through total number (and sign for direction)
     717                Translate(center);
     718        }
    719719};
    720720
     
    725725Vector * molecule::DetermineCenterOfAll(ofstream *out)
    726726{
    727   atom *ptr = start->next;  // start at first in list
    728   Vector *a = new Vector();
    729   Vector tmp;
    730   double Num = 0;
    731 
    732   a->Zero();
    733 
    734   if (ptr != end) {  //list not empty?
    735     while (ptr->next != end) {  // continue with second if present
    736       ptr = ptr->next;
    737       Num += 1.;
    738       tmp.CopyVector(&ptr->x);
    739       a->AddVector(&tmp);
    740     }
    741     a->Scale(-1./Num); // divide through total mass (and sign for direction)
    742   }
    743   //cout << Verbose(1) << "Resulting center of gravity: ";
    744   //a->Output(out);
    745   //cout << endl;
    746   return a;
     727        atom *ptr = start->next;        // start at first in list
     728        Vector *a = new Vector();
     729        Vector tmp;
     730        double Num = 0;
     731
     732        a->Zero();
     733
     734        if (ptr != end) {        //list not empty?
     735                while (ptr->next != end) {      // continue with second if present
     736                        ptr = ptr->next;
     737                        Num += 1.;
     738                        tmp.CopyVector(&ptr->x);
     739                        a->AddVector(&tmp);
     740                }
     741                a->Scale(-1./Num); // divide through total mass (and sign for direction)
     742        }
     743        //cout << Verbose(1) << "Resulting center of gravity: ";
     744        //a->Output(out);
     745        //cout << endl;
     746        return a;
    747747};
    748748
     
    753753Vector * molecule::DetermineCenterOfGravity(ofstream *out)
    754754{
    755         atom *ptr = start->next;  // start at first in list
     755        atom *ptr = start->next;        // start at first in list
    756756        Vector *a = new Vector();
    757757        Vector tmp;
    758   double Num = 0;
     758        double Num = 0;
    759759
    760760        a->Zero();
    761761
    762   if (ptr != end) {  //list not empty?
    763     while (ptr->next != end) {  // continue with second if present
    764       ptr = ptr->next;
    765       Num += ptr->type->mass;
    766       tmp.CopyVector(&ptr->x);
    767       tmp.Scale(ptr->type->mass);  // scale by mass
    768       a->AddVector(&tmp);
    769     }
    770     a->Scale(-1./Num); // divide through total mass (and sign for direction)
    771   }
    772 //  *out << Verbose(1) << "Resulting center of gravity: ";
    773 //  a->Output(out);
    774 //  *out << endl;
    775   return a;
     762        if (ptr != end) {        //list not empty?
     763                while (ptr->next != end) {      // continue with second if present
     764                        ptr = ptr->next;
     765                        Num += ptr->type->mass;
     766                        tmp.CopyVector(&ptr->x);
     767                        tmp.Scale(ptr->type->mass);     // scale by mass
     768                        a->AddVector(&tmp);
     769                }
     770                a->Scale(-1./Num); // divide through total mass (and sign for direction)
     771        }
     772//      *out << Verbose(1) << "Resulting center of gravity: ";
     773//      a->Output(out);
     774//      *out << endl;
     775        return a;
    776776};
    777777
     
    782782void molecule::CenterGravity(ofstream *out, Vector *center)
    783783{
    784   if (center == NULL) {
    785     DetermineCenter(*center);
    786     Translate(center);
    787     delete(center);
    788   } else {
    789     Translate(center);
    790   }
     784        if (center == NULL) {
     785                DetermineCenter(*center);
     786                Translate(center);
     787                delete(center);
     788        } else {
     789                Translate(center);
     790        }
    791791};
    792792
     
    796796void molecule::Scale(double **factor)
    797797{
    798   atom *ptr = start;
    799 
    800   while (ptr->next != end) {
    801     ptr = ptr->next;
    802     for (int j=0;j<MDSteps;j++)
    803       Trajectories[ptr].R.at(j).Scale(factor);
    804     ptr->x.Scale(factor);
    805   }
     798        atom *ptr = start;
     799
     800        while (ptr->next != end) {
     801                ptr = ptr->next;
     802                for (int j=0;j<MDSteps;j++)
     803                        Trajectories[ptr].R.at(j).Scale(factor);
     804                ptr->x.Scale(factor);
     805        }
    806806};
    807807
     
    811811void molecule::Translate(const Vector *trans)
    812812{
    813   atom *ptr = start;
    814 
    815   while (ptr->next != end) {
    816     ptr = ptr->next;
    817     for (int j=0;j<MDSteps;j++)
    818       Trajectories[ptr].R.at(j).Translate(trans);
    819     ptr->x.Translate(trans);
    820   }
     813        atom *ptr = start;
     814
     815        while (ptr->next != end) {
     816                ptr = ptr->next;
     817                for (int j=0;j<MDSteps;j++)
     818                        Trajectories[ptr].R.at(j).Translate(trans);
     819                ptr->x.Translate(trans);
     820        }
    821821};
    822822
     
    826826void molecule::Mirror(const Vector *n)
    827827{
    828   atom *ptr = start;
    829 
    830   while (ptr->next != end) {
    831     ptr = ptr->next;
    832     for (int j=0;j<MDSteps;j++)
    833       Trajectories[ptr].R.at(j).Mirror(n);
    834     ptr->x.Mirror(n);
    835   }
     828        atom *ptr = start;
     829
     830        while (ptr->next != end) {
     831                ptr = ptr->next;
     832                for (int j=0;j<MDSteps;j++)
     833                        Trajectories[ptr].R.at(j).Mirror(n);
     834                ptr->x.Mirror(n);
     835        }
    836836};
    837837
     
    841841void molecule::DetermineCenter(Vector &Center)
    842842{
    843   atom *Walker = start;
    844   bond *Binder = NULL;
    845   double *matrix = ReturnFullMatrixforSymmetric(cell_size);
    846   double tmp;
    847   bool flag;
    848   Vector Testvector, Translationvector;
    849 
    850   do {
    851     Center.Zero();
    852     flag = true;
    853     while (Walker->next != end) {
    854       Walker = Walker->next;
     843        atom *Walker = start;
     844        bond *Binder = NULL;
     845        double *matrix = ReturnFullMatrixforSymmetric(cell_size);
     846        double tmp;
     847        bool flag;
     848        Vector Testvector, Translationvector;
     849
     850        do {
     851                Center.Zero();
     852                flag = true;
     853                while (Walker->next != end) {
     854                        Walker = Walker->next;
    855855#ifdef ADDHYDROGEN
    856       if (Walker->type->Z != 1) {
     856                        if (Walker->type->Z != 1) {
    857857#endif
    858         Testvector.CopyVector(&Walker->x);
    859         Testvector.InverseMatrixMultiplication(matrix);
    860         Translationvector.Zero();
    861         for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {
    862           Binder = ListOfBondsPerAtom[Walker->nr][i];
    863           if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing
    864             for (int j=0;j<NDIM;j++) {
    865               tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j];
    866               if ((fabs(tmp)) > BondDistance) {
    867                 flag = false;
    868                 cout << Verbose(0) << "Hit: atom " << Walker->Name << " in bond " << *Binder << " has to be shifted due to " << tmp << "." << endl;
    869                 if (tmp > 0)
    870                   Translationvector.x[j] -= 1.;
    871                 else
    872                   Translationvector.x[j] += 1.;
    873               }
    874             }
    875         }
    876         Testvector.AddVector(&Translationvector);
    877         Testvector.MatrixMultiplication(matrix);
    878         Center.AddVector(&Testvector);
    879         cout << Verbose(1) << "vector is: ";
    880         Testvector.Output((ofstream *)&cout);
    881         cout << endl;
     858                                Testvector.CopyVector(&Walker->x);
     859                                Testvector.InverseMatrixMultiplication(matrix);
     860                                Translationvector.Zero();
     861                                for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {
     862                                        Binder = ListOfBondsPerAtom[Walker->nr][i];
     863                                        if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing
     864                                                for (int j=0;j<NDIM;j++) {
     865                                                        tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j];
     866                                                        if ((fabs(tmp)) > BondDistance) {
     867                                                                flag = false;
     868                                                                cout << Verbose(0) << "Hit: atom " << Walker->Name << " in bond " << *Binder << " has to be shifted due to " << tmp << "." << endl;
     869                                                                if (tmp > 0)
     870                                                                        Translationvector.x[j] -= 1.;
     871                                                                else
     872                                                                        Translationvector.x[j] += 1.;
     873                                                        }
     874                                                }
     875                                }
     876                                Testvector.AddVector(&Translationvector);
     877                                Testvector.MatrixMultiplication(matrix);
     878                                Center.AddVector(&Testvector);
     879                                cout << Verbose(1) << "vector is: ";
     880                                Testvector.Output((ofstream *)&cout);
     881                                cout << endl;
    882882#ifdef ADDHYDROGEN
    883         // now also change all hydrogens
    884         for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {
    885           Binder = ListOfBondsPerAtom[Walker->nr][i];
    886           if (Binder->GetOtherAtom(Walker)->type->Z == 1) {
    887             Testvector.CopyVector(&Binder->GetOtherAtom(Walker)->x);
    888             Testvector.InverseMatrixMultiplication(matrix);
    889             Testvector.AddVector(&Translationvector);
    890             Testvector.MatrixMultiplication(matrix);
    891             Center.AddVector(&Testvector);
    892             cout << Verbose(1) << "Hydrogen vector is: ";
    893             Testvector.Output((ofstream *)&cout);
    894             cout << endl;
    895           }
    896         }
    897       }
     883                                // now also change all hydrogens
     884                                for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {
     885                                        Binder = ListOfBondsPerAtom[Walker->nr][i];
     886                                        if (Binder->GetOtherAtom(Walker)->type->Z == 1) {
     887                                                Testvector.CopyVector(&Binder->GetOtherAtom(Walker)->x);
     888                                                Testvector.InverseMatrixMultiplication(matrix);
     889                                                Testvector.AddVector(&Translationvector);
     890                                                Testvector.MatrixMultiplication(matrix);
     891                                                Center.AddVector(&Testvector);
     892                                                cout << Verbose(1) << "Hydrogen vector is: ";
     893                                                Testvector.Output((ofstream *)&cout);
     894                                                cout << endl;
     895                                        }
     896                                }
     897                        }
    898898#endif
    899     }
    900   } while (!flag);
    901   Free((void **)&matrix, "molecule::DetermineCenter: *matrix");
    902   Center.Scale(1./(double)AtomCount);
     899                }
     900        } while (!flag);
     901        Free((void **)&matrix, "molecule::DetermineCenter: *matrix");
     902        Center.Scale(1./(double)AtomCount);
    903903};
    904904
     
    909909void molecule::PrincipalAxisSystem(ofstream *out, bool DoRotate)
    910910{
    911         atom *ptr = start;  // start at first in list
     911        atom *ptr = start;      // start at first in list
    912912        double InertiaTensor[NDIM*NDIM];
    913913        Vector *CenterOfGravity = DetermineCenterOfGravity(out);
     
    938938        *out << "The inertia tensor is:" << endl;
    939939        for(int i=0;i<NDIM;i++) {
    940           for(int j=0;j<NDIM;j++)
    941             *out << InertiaTensor[i*NDIM+j] << " ";
    942           *out << endl;
     940                for(int j=0;j<NDIM;j++)
     941                        *out << InertiaTensor[i*NDIM+j] << " ";
     942                *out << endl;
    943943        }
    944944        *out << endl;
     
    960960        // check whether we rotate or not
    961961        if (DoRotate) {
    962           *out << Verbose(1) << "Transforming molecule into PAS ... ";
    963           // the eigenvectors specify the transformation matrix
    964           ptr = start;
    965           while (ptr->next != end) {
    966             ptr = ptr->next;
    967             for (int j=0;j<MDSteps;j++)
    968               Trajectories[ptr].R.at(j).MatrixMultiplication(evec->data);
    969             ptr->x.MatrixMultiplication(evec->data);
    970           }
    971           *out << "done." << endl;
    972 
    973           // summing anew for debugging (resulting matrix has to be diagonal!)
    974           // reset inertia tensor
    975     for(int i=0;i<NDIM*NDIM;i++)
    976       InertiaTensor[i] = 0.;
    977 
    978     // sum up inertia tensor
    979     ptr = start;
    980     while (ptr->next != end) {
    981       ptr = ptr->next;
    982       Vector x;
    983       x.CopyVector(&ptr->x);
    984       //x.SubtractVector(CenterOfGravity);
    985       InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]);
    986       InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]);
    987       InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]);
    988       InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]);
    989       InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]);
    990       InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]);
    991       InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]);
    992       InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]);
    993       InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]);
    994     }
    995     // print InertiaTensor for debugging
    996     *out << "The inertia tensor is:" << endl;
    997     for(int i=0;i<NDIM;i++) {
    998       for(int j=0;j<NDIM;j++)
    999         *out << InertiaTensor[i*NDIM+j] << " ";
    1000       *out << endl;
    1001     }
    1002     *out << endl;
     962                *out << Verbose(1) << "Transforming molecule into PAS ... ";
     963                // the eigenvectors specify the transformation matrix
     964                ptr = start;
     965                while (ptr->next != end) {
     966                        ptr = ptr->next;
     967                        for (int j=0;j<MDSteps;j++)
     968                                Trajectories[ptr].R.at(j).MatrixMultiplication(evec->data);
     969                        ptr->x.MatrixMultiplication(evec->data);
     970                }
     971                *out << "done." << endl;
     972
     973                // summing anew for debugging (resulting matrix has to be diagonal!)
     974                // reset inertia tensor
     975                for(int i=0;i<NDIM*NDIM;i++)
     976                        InertiaTensor[i] = 0.;
     977
     978                // sum up inertia tensor
     979                ptr = start;
     980                while (ptr->next != end) {
     981                        ptr = ptr->next;
     982                        Vector x;
     983                        x.CopyVector(&ptr->x);
     984                        //x.SubtractVector(CenterOfGravity);
     985                        InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]);
     986                        InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]);
     987                        InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]);
     988                        InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]);
     989                        InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]);
     990                        InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]);
     991                        InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]);
     992                        InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]);
     993                        InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]);
     994                }
     995                // print InertiaTensor for debugging
     996                *out << "The inertia tensor is:" << endl;
     997                for(int i=0;i<NDIM;i++) {
     998                        for(int j=0;j<NDIM;j++)
     999                                *out << InertiaTensor[i*NDIM+j] << " ";
     1000                        *out << endl;
     1001                }
     1002                *out << endl;
    10031003        }
    10041004
     
    10201020bool molecule::VerletForceIntegration(char *file, double delta_t, bool IsAngstroem)
    10211021{
    1022   element *runner = elemente->start;
    1023   atom *walker = NULL;
    1024   int AtomNo;
    1025   ifstream input(file);
    1026   string token;
    1027   stringstream item;
    1028   double a, IonMass;
    1029   ForceMatrix Force;
    1030   Vector tmpvector;
    1031 
    1032   CountElements();  // make sure ElementsInMolecule is up to date
    1033 
    1034   // check file
    1035   if (input == NULL) {
    1036     return false;
    1037   } else {
    1038     // parse file into ForceMatrix
    1039     if (!Force.ParseMatrix(file, 0,0,0)) {
    1040       cerr << "Could not parse Force Matrix file " << file << "." << endl;
    1041       return false;
    1042     }
    1043     if (Force.RowCounter[0] != AtomCount) {
    1044       cerr << "Mismatch between number of atoms in file " << Force.RowCounter[0] << " and in molecule " << AtomCount << "." << endl;
    1045       return false;
    1046     }
    1047     // correct Forces
    1048 //    for(int d=0;d<NDIM;d++)
    1049 //      tmpvector.x[d] = 0.;
    1050 //    for(int i=0;i<AtomCount;i++)
    1051 //      for(int d=0;d<NDIM;d++) {
    1052 //        tmpvector.x[d] += Force.Matrix[0][i][d+5];
    1053 //      }
    1054 //    for(int i=0;i<AtomCount;i++)
    1055 //      for(int d=0;d<NDIM;d++) {
    1056 //        Force.Matrix[0][i][d+5] -= tmpvector.x[d]/(double)AtomCount;
    1057 //      }
    1058     // and perform Verlet integration for each atom with position, velocity and force vector
    1059     runner = elemente->start;
    1060     while (runner->next != elemente->end) { // go through every element
    1061       runner = runner->next;
    1062       IonMass = runner->mass;
    1063       a = delta_t*0.5/IonMass;        // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a
    1064       if (ElementsInMolecule[runner->Z]) { // if this element got atoms
    1065         AtomNo = 0;
    1066         walker = start;
    1067         while (walker->next != end) { // go through every atom of this element
    1068           walker = walker->next;
    1069           if (walker->type == runner) { // if this atom fits to element
    1070             // check size of vectors
    1071             if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) {
    1072               //cout << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl;
    1073               Trajectories[walker].R.resize(MDSteps+10);
    1074               Trajectories[walker].U.resize(MDSteps+10);
    1075               Trajectories[walker].F.resize(MDSteps+10);
    1076             }
    1077             // 1. calculate x(t+\delta t)
    1078             for (int d=0; d<NDIM; d++) {
    1079               Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5];
    1080               Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d];
    1081               Trajectories[walker].R.at(MDSteps).x[d] += delta_t*(Trajectories[walker].U.at(MDSteps-1).x[d]);
    1082               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
    1083             }
    1084             // 2. Calculate v(t+\delta t)
    1085             for (int d=0; d<NDIM; d++) {
    1086               Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d];
    1087               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;
    1088             }
    1089 //            cout << "Integrated position&velocity of step " << (MDSteps) << ": (";
    1090 //            for (int d=0;d<NDIM;d++)
    1091 //              cout << Trajectories[walker].R.at(MDSteps).x[d] << " ";          // next step
    1092 //            cout << ")\t(";
    1093 //            for (int d=0;d<NDIM;d++)
    1094 //              cout << Trajectories[walker].U.at(MDSteps).x[d] << " ";          // next step
    1095 //            cout << ")" << endl;
    1096             // next atom
    1097             AtomNo++;
    1098           }
    1099         }
    1100       }
    1101     }
    1102   }
    1103 //  // correct velocities (rather momenta) so that center of mass remains motionless
    1104 //  tmpvector.zero()
    1105 //  IonMass = 0.;
    1106 //  walker = start;
    1107 //  while (walker->next != end) { // go through every atom
    1108 //    walker = walker->next;
    1109 //    IonMass += walker->type->mass;  // sum up total mass
    1110 //    for(int d=0;d<NDIM;d++) {
    1111 //      tmpvector.x[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass;
    1112 //    }
    1113 //  }
    1114 //  walker = start;
    1115 //  while (walker->next != end) { // go through every atom of this element
    1116 //    walker = walker->next;
    1117 //    for(int d=0;d<NDIM;d++) {
    1118 //      Trajectories[walker].U.at(MDSteps).x[d] -= tmpvector.x[d]*walker->type->mass/IonMass;
    1119 //    }
    1120 //  }
    1121   MDSteps++;
    1122 
    1123 
    1124   // exit
    1125   return true;
     1022        element *runner = elemente->start;
     1023        atom *walker = NULL;
     1024        int AtomNo;
     1025        ifstream input(file);
     1026        string token;
     1027        stringstream item;
     1028        double a, IonMass;
     1029        ForceMatrix Force;
     1030        Vector tmpvector;
     1031
     1032        CountElements();        // make sure ElementsInMolecule is up to date
     1033
     1034        // check file
     1035        if (input == NULL) {
     1036                return false;
     1037        } else {
     1038                // parse file into ForceMatrix
     1039                if (!Force.ParseMatrix(file, 0,0,0)) {
     1040                        cerr << "Could not parse Force Matrix file " << file << "." << endl;
     1041                        return false;
     1042                }
     1043                if (Force.RowCounter[0] != AtomCount) {
     1044                        cerr << "Mismatch between number of atoms in file " << Force.RowCounter[0] << " and in molecule " << AtomCount << "." << endl;
     1045                        return false;
     1046                }
     1047                // correct Forces
     1048//              for(int d=0;d<NDIM;d++)
     1049//                      tmpvector.x[d] = 0.;
     1050//              for(int i=0;i<AtomCount;i++)
     1051//                      for(int d=0;d<NDIM;d++) {
     1052//                              tmpvector.x[d] += Force.Matrix[0][i][d+5];
     1053//                      }
     1054//              for(int i=0;i<AtomCount;i++)
     1055//                      for(int d=0;d<NDIM;d++) {
     1056//                              Force.Matrix[0][i][d+5] -= tmpvector.x[d]/(double)AtomCount;
     1057//                      }
     1058                // and perform Verlet integration for each atom with position, velocity and force vector
     1059                runner = elemente->start;
     1060                while (runner->next != elemente->end) { // go through every element
     1061                        runner = runner->next;
     1062                        IonMass = runner->mass;
     1063                        a = delta_t*0.5/IonMass;                                // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a
     1064                        if (ElementsInMolecule[runner->Z]) { // if this element got atoms
     1065                                AtomNo = 0;
     1066                                walker = start;
     1067                                while (walker->next != end) { // go through every atom of this element
     1068                                        walker = walker->next;
     1069                                        if (walker->type == runner) { // if this atom fits to element
     1070                                                // check size of vectors
     1071                                                if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) {
     1072                                                        //cout << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl;
     1073                                                        Trajectories[walker].R.resize(MDSteps+10);
     1074                                                        Trajectories[walker].U.resize(MDSteps+10);
     1075                                                        Trajectories[walker].F.resize(MDSteps+10);
     1076                                                }
     1077                                                // 1. calculate x(t+\delta t)
     1078                                                for (int d=0; d<NDIM; d++) {
     1079                                                        Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5];
     1080                                                        Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d];
     1081                                                        Trajectories[walker].R.at(MDSteps).x[d] += delta_t*(Trajectories[walker].U.at(MDSteps-1).x[d]);
     1082                                                        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
     1083                                                }
     1084                                                // 2. Calculate v(t+\delta t)
     1085                                                for (int d=0; d<NDIM; d++) {
     1086                                                        Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d];
     1087                                                        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;
     1088                                                }
     1089//                                              cout << "Integrated position&velocity of step " << (MDSteps) << ": (";
     1090//                                              for (int d=0;d<NDIM;d++)
     1091//                                                      cout << Trajectories[walker].R.at(MDSteps).x[d] << " ";                                 // next step
     1092//                                              cout << ")\t(";
     1093//                                              for (int d=0;d<NDIM;d++)
     1094//                                                      cout << Trajectories[walker].U.at(MDSteps).x[d] << " ";                                 // next step
     1095//                                              cout << ")" << endl;
     1096                                                // next atom
     1097                                                AtomNo++;
     1098                                        }
     1099                                }
     1100                        }
     1101                }
     1102        }
     1103//      // correct velocities (rather momenta) so that center of mass remains motionless
     1104//      tmpvector.zero()
     1105//      IonMass = 0.;
     1106//      walker = start;
     1107//      while (walker->next != end) { // go through every atom
     1108//              walker = walker->next;
     1109//              IonMass += walker->type->mass;  // sum up total mass
     1110//              for(int d=0;d<NDIM;d++) {
     1111//                      tmpvector.x[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass;
     1112//              }
     1113//      }
     1114//      walker = start;
     1115//      while (walker->next != end) { // go through every atom of this element
     1116//              walker = walker->next;
     1117//              for(int d=0;d<NDIM;d++) {
     1118//                      Trajectories[walker].U.at(MDSteps).x[d] -= tmpvector.x[d]*walker->type->mass/IonMass;
     1119//              }
     1120//      }
     1121        MDSteps++;
     1122
     1123
     1124        // exit
     1125        return true;
    11261126};
    11271127
     
    11311131void molecule::Align(Vector *n)
    11321132{
    1133   atom *ptr = start;
    1134   double alpha, tmp;
    1135   Vector z_axis;
    1136   z_axis.x[0] = 0.;
    1137   z_axis.x[1] = 0.;
    1138   z_axis.x[2] = 1.;
    1139 
    1140   // rotate on z-x plane
    1141   cout << Verbose(0) << "Begin of Aligning all atoms." << endl;
    1142   alpha = atan(-n->x[0]/n->x[2]);
    1143   cout << Verbose(1) << "Z-X-angle: " << alpha << " ... ";
    1144   while (ptr->next != end) {
    1145     ptr = ptr->next;
    1146     tmp = ptr->x.x[0];
    1147     ptr->x.x[0] =  cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];
    1148     ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];
    1149     for (int j=0;j<MDSteps;j++) {
    1150       tmp = Trajectories[ptr].R.at(j).x[0];
    1151       Trajectories[ptr].R.at(j).x[0] =  cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];
    1152       Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2];
    1153     }
    1154   }
    1155   // rotate n vector
    1156   tmp = n->x[0];
    1157   n->x[0] =  cos(alpha) * tmp +  sin(alpha) * n->x[2];
    1158   n->x[2] = -sin(alpha) * tmp +  cos(alpha) * n->x[2];
    1159   cout << Verbose(1) << "alignment vector after first rotation: ";
    1160   n->Output((ofstream *)&cout);
    1161   cout << endl;
    1162 
    1163   // rotate on z-y plane
    1164   ptr = start;
    1165   alpha = atan(-n->x[1]/n->x[2]);
    1166   cout << Verbose(1) << "Z-Y-angle: " << alpha << " ... ";
    1167   while (ptr->next != end) {
    1168     ptr = ptr->next;
    1169     tmp = ptr->x.x[1];
    1170     ptr->x.x[1] =  cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];
    1171     ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];
    1172     for (int j=0;j<MDSteps;j++) {
    1173       tmp = Trajectories[ptr].R.at(j).x[1];
    1174       Trajectories[ptr].R.at(j).x[1] =  cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];
    1175       Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2];
    1176     }
    1177   }
    1178   // rotate n vector (for consistency check)
    1179   tmp = n->x[1];
    1180   n->x[1] =  cos(alpha) * tmp +  sin(alpha) * n->x[2];
    1181   n->x[2] = -sin(alpha) * tmp +  cos(alpha) * n->x[2];
    1182 
    1183   cout << Verbose(1) << "alignment vector after second rotation: ";
    1184   n->Output((ofstream *)&cout);
    1185   cout << Verbose(1) << endl;
    1186   cout << Verbose(0) << "End of Aligning all atoms." << endl;
     1133        atom *ptr = start;
     1134        double alpha, tmp;
     1135        Vector z_axis;
     1136        z_axis.x[0] = 0.;
     1137        z_axis.x[1] = 0.;
     1138        z_axis.x[2] = 1.;
     1139
     1140        // rotate on z-x plane
     1141        cout << Verbose(0) << "Begin of Aligning all atoms." << endl;
     1142        alpha = atan(-n->x[0]/n->x[2]);
     1143        cout << Verbose(1) << "Z-X-angle: " << alpha << " ... ";
     1144        while (ptr->next != end) {
     1145                ptr = ptr->next;
     1146                tmp = ptr->x.x[0];
     1147                ptr->x.x[0] =   cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];
     1148                ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];
     1149                for (int j=0;j<MDSteps;j++) {
     1150                        tmp = Trajectories[ptr].R.at(j).x[0];
     1151                        Trajectories[ptr].R.at(j).x[0] =        cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];
     1152                        Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2];
     1153                }
     1154        }
     1155        // rotate n vector
     1156        tmp = n->x[0];
     1157        n->x[0] =       cos(alpha) * tmp +      sin(alpha) * n->x[2];
     1158        n->x[2] = -sin(alpha) * tmp +   cos(alpha) * n->x[2];
     1159        cout << Verbose(1) << "alignment vector after first rotation: ";
     1160        n->Output((ofstream *)&cout);
     1161        cout << endl;
     1162
     1163        // rotate on z-y plane
     1164        ptr = start;
     1165        alpha = atan(-n->x[1]/n->x[2]);
     1166        cout << Verbose(1) << "Z-Y-angle: " << alpha << " ... ";
     1167        while (ptr->next != end) {
     1168                ptr = ptr->next;
     1169                tmp = ptr->x.x[1];
     1170                ptr->x.x[1] =   cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];
     1171                ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];
     1172                for (int j=0;j<MDSteps;j++) {
     1173                        tmp = Trajectories[ptr].R.at(j).x[1];
     1174                        Trajectories[ptr].R.at(j).x[1] =        cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];
     1175                        Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2];
     1176                }
     1177        }
     1178        // rotate n vector (for consistency check)
     1179        tmp = n->x[1];
     1180        n->x[1] =       cos(alpha) * tmp +      sin(alpha) * n->x[2];
     1181        n->x[2] = -sin(alpha) * tmp +   cos(alpha) * n->x[2];
     1182
     1183        cout << Verbose(1) << "alignment vector after second rotation: ";
     1184        n->Output((ofstream *)&cout);
     1185        cout << Verbose(1) << endl;
     1186        cout << Verbose(0) << "End of Aligning all atoms." << endl;
    11871187};
    11881188
     
    11931193bool molecule::RemoveAtom(atom *pointer)
    11941194{
    1195   if (ElementsInMolecule[pointer->type->Z] != 0)  // this would indicate an error
    1196     ElementsInMolecule[pointer->type->Z]--;  // decrease number of atom of this element
    1197   else
    1198     cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl;
    1199   if (ElementsInMolecule[pointer->type->Z] == 0)  // was last atom of this element?
    1200     ElementCount--;
    1201   Trajectories.erase(pointer);
    1202   return remove(pointer, start, end);
     1195        if (ElementsInMolecule[pointer->type->Z] != 0)  // this would indicate an error
     1196                ElementsInMolecule[pointer->type->Z]--; // decrease number of atom of this element
     1197        else
     1198                cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl;
     1199        if (ElementsInMolecule[pointer->type->Z] == 0)  // was last atom of this element?
     1200                ElementCount--;
     1201        Trajectories.erase(pointer);
     1202        return remove(pointer, start, end);
    12031203};
    12041204
     
    12081208bool molecule::CleanupMolecule()
    12091209{
    1210   return (cleanup(start,end) && cleanup(first,last));
     1210        return (cleanup(start,end) && cleanup(first,last));
    12111211};
    12121212
     
    12151215 * \return pointer to atom or NULL
    12161216 */
    1217 atom * molecule::FindAtom(int Nr)  const{
    1218   atom * walker = find(&Nr, start,end);
    1219   if (walker != NULL) {
    1220     //cout << Verbose(0) << "Found Atom Nr. " << walker->nr << endl;
    1221     return walker;
    1222   } else {
    1223     cout << Verbose(0) << "Atom not found in list." << endl;
    1224     return NULL;
    1225   }
     1217atom * molecule::FindAtom(int Nr)       const{
     1218        atom * walker = find(&Nr, start,end);
     1219        if (walker != NULL) {
     1220                //cout << Verbose(0) << "Found Atom Nr. " << walker->nr << endl;
     1221                return walker;
     1222        } else {
     1223                cout << Verbose(0) << "Atom not found in list." << endl;
     1224                return NULL;
     1225        }
    12261226};
    12271227
     
    12311231atom * molecule::AskAtom(string text)
    12321232{
    1233   int No;
    1234   atom *ion = NULL;
    1235   do {
    1236     //cout << Verbose(0) << "============Atom list==========================" << endl;
    1237     //mol->Output((ofstream *)&cout);
    1238     //cout << Verbose(0) << "===============================================" << endl;
    1239     cout << Verbose(0) << text;
    1240     cin >> No;
    1241     ion = this->FindAtom(No);
    1242   } while (ion == NULL);
    1243   return ion;
     1233        int No;
     1234        atom *ion = NULL;
     1235        do {
     1236                //cout << Verbose(0) << "============Atom list==========================" << endl;
     1237                //mol->Output((ofstream *)&cout);
     1238                //cout << Verbose(0) << "===============================================" << endl;
     1239                cout << Verbose(0) << text;
     1240                cin >> No;
     1241                ion = this->FindAtom(No);
     1242        } while (ion == NULL);
     1243        return ion;
    12441244};
    12451245
     
    12501250bool molecule::CheckBounds(const Vector *x) const
    12511251{
    1252   bool result = true;
    1253   int j =-1;
    1254   for (int i=0;i<NDIM;i++) {
    1255     j += i+1;
    1256     result = result && ((x->x[i] >= 0) && (x->x[i] < cell_size[j]));
    1257   }
    1258   //return result;
    1259   return true; /// probably not gonna use the check no more
     1252        bool result = true;
     1253        int j =-1;
     1254        for (int i=0;i<NDIM;i++) {
     1255                j += i+1;
     1256                result = result && ((x->x[i] >= 0) && (x->x[i] < cell_size[j]));
     1257        }
     1258        //return result;
     1259        return true; /// probably not gonna use the check no more
    12601260};
    12611261
     
    12671267double LeastSquareDistance (const gsl_vector * x, void * params)
    12681268{
    1269   double res = 0, t;
    1270   Vector a,b,c,d;
    1271   struct lsq_params *par = (struct lsq_params *)params;
    1272   atom *ptr = par->mol->start;
    1273 
    1274   // initialize vectors
    1275   a.x[0] = gsl_vector_get(x,0);
    1276   a.x[1] = gsl_vector_get(x,1);
    1277   a.x[2] = gsl_vector_get(x,2);
    1278   b.x[0] = gsl_vector_get(x,3);
    1279   b.x[1] = gsl_vector_get(x,4);
    1280   b.x[2] = gsl_vector_get(x,5);
    1281   // go through all atoms
    1282   while (ptr != par->mol->end) {
    1283     ptr = ptr->next;
    1284     if (ptr->type == ((struct lsq_params *)params)->type) { // for specific type
    1285       c.CopyVector(&ptr->x);  // copy vector to temporary one
    1286       c.SubtractVector(&a);  // subtract offset vector
    1287       t = c.ScalarProduct(&b);          // get direction parameter
    1288       d.CopyVector(&b);      // and create vector
    1289       d.Scale(&t);
    1290       c.SubtractVector(&d);  // ... yielding distance vector
    1291       res += d.ScalarProduct((const Vector *)&d);        // add squared distance
    1292     }
    1293   }
    1294   return res;
     1269        double res = 0, t;
     1270        Vector a,b,c,d;
     1271        struct lsq_params *par = (struct lsq_params *)params;
     1272        atom *ptr = par->mol->start;
     1273
     1274        // initialize vectors
     1275        a.x[0] = gsl_vector_get(x,0);
     1276        a.x[1] = gsl_vector_get(x,1);
     1277        a.x[2] = gsl_vector_get(x,2);
     1278        b.x[0] = gsl_vector_get(x,3);
     1279        b.x[1] = gsl_vector_get(x,4);
     1280        b.x[2] = gsl_vector_get(x,5);
     1281        // go through all atoms
     1282        while (ptr != par->mol->end) {
     1283                ptr = ptr->next;
     1284                if (ptr->type == ((struct lsq_params *)params)->type) { // for specific type
     1285                        c.CopyVector(&ptr->x);  // copy vector to temporary one
     1286                        c.SubtractVector(&a);    // subtract offset vector
     1287                        t = c.ScalarProduct(&b);                                        // get direction parameter
     1288                        d.CopyVector(&b);                        // and create vector
     1289                        d.Scale(&t);
     1290                        c.SubtractVector(&d);    // ... yielding distance vector
     1291                        res += d.ScalarProduct((const Vector *)&d);                             // add squared distance
     1292                }
     1293        }
     1294        return res;
    12951295};
    12961296
     
    13001300void molecule::GetAlignvector(struct lsq_params * par) const
    13011301{
    1302     int np = 6;
    1303 
    1304   const gsl_multimin_fminimizer_type *T =
    1305     gsl_multimin_fminimizer_nmsimplex;
    1306   gsl_multimin_fminimizer *s = NULL;
    1307   gsl_vector *ss;
    1308   gsl_multimin_function minex_func;
    1309 
    1310   size_t iter = 0, i;
    1311   int status;
    1312   double size;
    1313 
    1314   /* Initial vertex size vector */
    1315   ss = gsl_vector_alloc (np);
    1316 
    1317   /* Set all step sizes to 1 */
    1318   gsl_vector_set_all (ss, 1.0);
    1319 
    1320   /* Starting point */
    1321   par->x = gsl_vector_alloc (np);
    1322   par->mol = this;
    1323 
    1324    gsl_vector_set (par->x, 0, 0.0);  // offset
    1325   gsl_vector_set (par->x, 1, 0.0);
    1326   gsl_vector_set (par->x, 2, 0.0);
    1327    gsl_vector_set (par->x, 3, 0.0);  // direction
    1328   gsl_vector_set (par->x, 4, 0.0);
    1329   gsl_vector_set (par->x, 5, 1.0);
    1330 
    1331   /* Initialize method and iterate */
    1332   minex_func.f = &LeastSquareDistance;
    1333   minex_func.n = np;
    1334   minex_func.params = (void *)par;
    1335 
    1336   s = gsl_multimin_fminimizer_alloc (T, np);
    1337   gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss);
    1338 
    1339   do
    1340     {
    1341       iter++;
    1342       status = gsl_multimin_fminimizer_iterate(s);
    1343 
    1344       if (status)
    1345         break;
    1346 
    1347       size = gsl_multimin_fminimizer_size (s);
    1348       status = gsl_multimin_test_size (size, 1e-2);
    1349 
    1350       if (status == GSL_SUCCESS)
    1351         {
    1352           printf ("converged to minimum at\n");
    1353         }
    1354 
    1355       printf ("%5d ", (int)iter);
    1356       for (i = 0; i < (size_t)np; i++)
    1357         {
    1358           printf ("%10.3e ", gsl_vector_get (s->x, i));
    1359         }
    1360       printf ("f() = %7.3f size = %.3f\n", s->fval, size);
    1361     }
    1362   while (status == GSL_CONTINUE && iter < 100);
    1363 
    1364   for (i=0;i<(size_t)np;i++)
    1365     gsl_vector_set(par->x, i, gsl_vector_get(s->x, i));
    1366   //gsl_vector_free(par->x);
    1367   gsl_vector_free(ss);
    1368   gsl_multimin_fminimizer_free (s);
     1302                int np = 6;
     1303
     1304        const gsl_multimin_fminimizer_type *T =
     1305                gsl_multimin_fminimizer_nmsimplex;
     1306        gsl_multimin_fminimizer *s = NULL;
     1307        gsl_vector *ss;
     1308        gsl_multimin_function minex_func;
     1309
     1310        size_t iter = 0, i;
     1311        int status;
     1312        double size;
     1313
     1314        /* Initial vertex size vector */
     1315        ss = gsl_vector_alloc (np);
     1316
     1317        /* Set all step sizes to 1 */
     1318        gsl_vector_set_all (ss, 1.0);
     1319
     1320        /* Starting point */
     1321        par->x = gsl_vector_alloc (np);
     1322        par->mol = this;
     1323
     1324         gsl_vector_set (par->x, 0, 0.0);       // offset
     1325        gsl_vector_set (par->x, 1, 0.0);
     1326        gsl_vector_set (par->x, 2, 0.0);
     1327         gsl_vector_set (par->x, 3, 0.0);       // direction
     1328        gsl_vector_set (par->x, 4, 0.0);
     1329        gsl_vector_set (par->x, 5, 1.0);
     1330
     1331        /* Initialize method and iterate */
     1332        minex_func.f = &LeastSquareDistance;
     1333        minex_func.n = np;
     1334        minex_func.params = (void *)par;
     1335
     1336        s = gsl_multimin_fminimizer_alloc (T, np);
     1337        gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss);
     1338
     1339        do
     1340                {
     1341                        iter++;
     1342                        status = gsl_multimin_fminimizer_iterate(s);
     1343
     1344                        if (status)
     1345                                break;
     1346
     1347                        size = gsl_multimin_fminimizer_size (s);
     1348                        status = gsl_multimin_test_size (size, 1e-2);
     1349
     1350                        if (status == GSL_SUCCESS)
     1351                                {
     1352                                        printf ("converged to minimum at\n");
     1353                                }
     1354
     1355                        printf ("%5d ", (int)iter);
     1356                        for (i = 0; i < (size_t)np; i++)
     1357                                {
     1358                                        printf ("%10.3e ", gsl_vector_get (s->x, i));
     1359                                }
     1360                        printf ("f() = %7.3f size = %.3f\n", s->fval, size);
     1361                }
     1362        while (status == GSL_CONTINUE && iter < 100);
     1363
     1364        for (i=0;i<(size_t)np;i++)
     1365                gsl_vector_set(par->x, i, gsl_vector_get(s->x, i));
     1366        //gsl_vector_free(par->x);
     1367        gsl_vector_free(ss);
     1368        gsl_multimin_fminimizer_free (s);
    13691369};
    13701370
     
    13741374bool molecule::Output(ofstream *out)
    13751375{
    1376   element *runner;
    1377   atom *walker = NULL;
    1378   int ElementNo, AtomNo;
    1379   CountElements();
    1380 
    1381   if (out == NULL) {
    1382     return false;
    1383   } else {
    1384     *out << "#Ion_TypeNr._Nr.R[0]    R[1]    R[2]    MoveType (0 MoveIon, 1 FixedIon)" << endl;
    1385     ElementNo = 0;
    1386     runner = elemente->start;
    1387     while (runner->next != elemente->end) { // go through every element
    1388                 runner = runner->next;
    1389       if (ElementsInMolecule[runner->Z]) { // if this element got atoms
    1390         ElementNo++;
    1391         AtomNo = 0;
    1392         walker = start;
    1393         while (walker->next != end) { // go through every atom of this element
    1394           walker = walker->next;
    1395           if (walker->type == runner) { // if this atom fits to element
    1396             AtomNo++;
    1397             walker->Output(ElementNo, AtomNo, out); // removed due to trajectories
    1398           }
    1399         }
    1400       }
    1401     }
    1402     return true;
    1403   }
     1376        element *runner;
     1377        atom *walker = NULL;
     1378        int ElementNo, AtomNo;
     1379        CountElements();
     1380
     1381        if (out == NULL) {
     1382                return false;
     1383        } else {
     1384                *out << "#Ion_TypeNr._Nr.R[0]           R[1]            R[2]            MoveType (0 MoveIon, 1 FixedIon)" << endl;
     1385                ElementNo = 0;
     1386                runner = elemente->start;
     1387                while (runner->next != elemente->end) { // go through every element
     1388                        runner = runner->next;
     1389                        if (ElementsInMolecule[runner->Z]) { // if this element got atoms
     1390                                ElementNo++;
     1391                                AtomNo = 0;
     1392                                walker = start;
     1393                                while (walker->next != end) { // go through every atom of this element
     1394                                        walker = walker->next;
     1395                                        if (walker->type == runner) { // if this atom fits to element
     1396                                                AtomNo++;
     1397                                                walker->Output(ElementNo, AtomNo, out); // removed due to trajectories
     1398                                        }
     1399                                }
     1400                        }
     1401                }
     1402                return true;
     1403        }
    14041404};
    14051405
     
    14091409bool molecule::OutputTrajectories(ofstream *out)
    14101410{
    1411   element *runner = NULL;
    1412   atom *walker = NULL;
    1413   int ElementNo, AtomNo;
    1414   CountElements();
    1415 
    1416   if (out == NULL) {
    1417     return false;
    1418   } else {
    1419     for (int step = 0; step < MDSteps; step++) {
    1420       if (step == 0) {
    1421         *out << "#Ion_TypeNr._Nr.R[0]    R[1]    R[2]    MoveType (0 MoveIon, 1 FixedIon)" << endl;
    1422       } else {
    1423         *out << "# ====== MD step " << step << " =========" << endl;
    1424       }
    1425       ElementNo = 0;
    1426       runner = elemente->start;
    1427       while (runner->next != elemente->end) { // go through every element
    1428         runner = runner->next;
    1429         if (ElementsInMolecule[runner->Z]) { // if this element got atoms
    1430           ElementNo++;
    1431           AtomNo = 0;
    1432           walker = start;
    1433           while (walker->next != end) { // go through every atom of this element
    1434             walker = walker->next;
    1435             if (walker->type == runner) { // if this atom fits to element
    1436               AtomNo++;
    1437               *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t"  << fixed << setprecision(9) << showpoint;
    1438               *out << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2];
    1439               *out << "\t" << walker->FixedIon;
    1440               if (Trajectories[walker].U.at(step).Norm() > MYEPSILON)
    1441                 *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";
    1442               if (Trajectories[walker].F.at(step).Norm() > MYEPSILON)
    1443                 *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";
    1444               *out << "\t# Number in molecule " << walker->nr << endl;
    1445             }
    1446           }
    1447         }
    1448       }
    1449     }
    1450     return true;
    1451   }
     1411        element *runner = NULL;
     1412        atom *walker = NULL;
     1413        int ElementNo, AtomNo;
     1414        CountElements();
     1415
     1416        if (out == NULL) {
     1417                return false;
     1418        } else {
     1419                for (int step = 0; step < MDSteps; step++) {
     1420                        if (step == 0) {
     1421                                *out << "#Ion_TypeNr._Nr.R[0]           R[1]            R[2]            MoveType (0 MoveIon, 1 FixedIon)" << endl;
     1422                        } else {
     1423                                *out << "# ====== MD step " << step << " =========" << endl;
     1424                        }
     1425                        ElementNo = 0;
     1426                        runner = elemente->start;
     1427                        while (runner->next != elemente->end) { // go through every element
     1428                                runner = runner->next;
     1429                                if (ElementsInMolecule[runner->Z]) { // if this element got atoms
     1430                                        ElementNo++;
     1431                                        AtomNo = 0;
     1432                                        walker = start;
     1433                                        while (walker->next != end) { // go through every atom of this element
     1434                                                walker = walker->next;
     1435                                                if (walker->type == runner) { // if this atom fits to element
     1436                                                        AtomNo++;
     1437                                                        *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t"        << fixed << setprecision(9) << showpoint;
     1438                                                        *out << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2];
     1439                                                        *out << "\t" << walker->FixedIon;
     1440                                                        if (Trajectories[walker].U.at(step).Norm() > MYEPSILON)
     1441                                                                *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";
     1442                                                        if (Trajectories[walker].F.at(step).Norm() > MYEPSILON)
     1443                                                                *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";
     1444                                                        *out << "\t# Number in molecule " << walker->nr << endl;
     1445                                                }
     1446                                        }
     1447                                }
     1448                        }
     1449                }
     1450                return true;
     1451        }
    14521452};
    14531453
     
    14571457void molecule::OutputListOfBonds(ofstream *out) const
    14581458{
    1459   *out << Verbose(2) << endl << "From Contents of ListOfBondsPerAtom, all non-hydrogen atoms:" << endl;
    1460   atom *Walker = start;
    1461   while (Walker->next != end) {
    1462     Walker = Walker->next;
     1459        *out << Verbose(2) << endl << "From Contents of ListOfBondsPerAtom, all non-hydrogen atoms:" << endl;
     1460        atom *Walker = start;
     1461        while (Walker->next != end) {
     1462                Walker = Walker->next;
    14631463#ifdef ADDHYDROGEN
    1464     if (Walker->type->Z != 1) {  // regard only non-hydrogen
     1464                if (Walker->type->Z != 1) {      // regard only non-hydrogen
    14651465#endif
    1466       *out << Verbose(2) << "Atom " << Walker->Name << " has Bonds: "<<endl;
    1467       for(int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) {
    1468         *out << Verbose(3) << *(ListOfBondsPerAtom)[Walker->nr][j] << endl;
    1469       }
     1466                        *out << Verbose(2) << "Atom " << Walker->Name << " has Bonds: "<<endl;
     1467                        for(int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) {
     1468                                *out << Verbose(3) << *(ListOfBondsPerAtom)[Walker->nr][j] << endl;
     1469                        }
    14701470#ifdef ADDHYDROGEN
    1471     }
     1471                }
    14721472#endif
    1473   }
    1474   *out << endl;
     1473        }
     1474        *out << endl;
    14751475};
    14761476
     
    14781478 * \param *out stream pointer
    14791479 */
    1480 bool molecule::Checkout(ofstream *out)  const
     1480bool molecule::Checkout(ofstream *out)  const
    14811481{
    14821482        return elemente->Checkout(out, ElementsInMolecule);
     
    14881488bool molecule::OutputTrajectoriesXYZ(ofstream *out)
    14891489{
    1490   atom *walker = NULL;
    1491   int No = 0;
    1492   time_t now;
    1493 
    1494   now = time((time_t *)NULL);  // Get the system time and put it into 'now' as 'calender time'
    1495   walker = start;
    1496   while (walker->next != end) { // go through every atom and count
    1497     walker = walker->next;
    1498     No++;
    1499   }
    1500   if (out != NULL) {
    1501     for (int step=0;step<MDSteps;step++) {
    1502       *out << No << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now);
    1503       walker = start;
    1504       while (walker->next != end) { // go through every atom of this element
    1505         walker = walker->next;
    1506         *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;
    1507       }
    1508     }
    1509     return true;
    1510   } else
    1511     return false;
     1490        atom *walker = NULL;
     1491        int No = 0;
     1492        time_t now;
     1493
     1494        now = time((time_t *)NULL);      // Get the system time and put it into 'now' as 'calender time'
     1495        walker = start;
     1496        while (walker->next != end) { // go through every atom and count
     1497                walker = walker->next;
     1498                No++;
     1499        }
     1500        if (out != NULL) {
     1501                for (int step=0;step<MDSteps;step++) {
     1502                        *out << No << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now);
     1503                        walker = start;
     1504                        while (walker->next != end) { // go through every atom of this element
     1505                                walker = walker->next;
     1506                                *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;
     1507                        }
     1508                }
     1509                return true;
     1510        } else
     1511                return false;
    15121512};
    15131513
     
    15171517bool molecule::OutputXYZ(ofstream *out) const
    15181518{
    1519   atom *walker = NULL;
    1520   int AtomNo = 0, ElementNo;
    1521   time_t now;
    1522   element *runner = NULL;
    1523 
    1524   now = time((time_t *)NULL);  // Get the system time and put it into 'now' as 'calender time'
    1525   walker = start;
    1526   while (walker->next != end) { // go through every atom and count
    1527     walker = walker->next;
    1528     AtomNo++;
    1529   }
    1530   if (out != NULL) {
    1531     *out << AtomNo << "\n\tCreated by molecuilder on " << ctime(&now);
    1532     ElementNo = 0;
    1533     runner = elemente->start;
    1534     while (runner->next != elemente->end) { // go through every element
    1535                 runner = runner->next;
    1536       if (ElementsInMolecule[runner->Z]) { // if this element got atoms
    1537         ElementNo++;
    1538         walker = start;
    1539         while (walker->next != end) { // go through every atom of this element
    1540           walker = walker->next;
    1541           if (walker->type == runner) { // if this atom fits to element
    1542             walker->OutputXYZLine(out);
    1543           }
    1544         }
    1545       }
    1546     }
    1547     return true;
    1548   } else
    1549     return false;
     1519        atom *walker = NULL;
     1520        int AtomNo = 0, ElementNo;
     1521        time_t now;
     1522        element *runner = NULL;
     1523
     1524        now = time((time_t *)NULL);      // Get the system time and put it into 'now' as 'calender time'
     1525        walker = start;
     1526        while (walker->next != end) { // go through every atom and count
     1527                walker = walker->next;
     1528                AtomNo++;
     1529        }
     1530        if (out != NULL) {
     1531                *out << AtomNo << "\n\tCreated by molecuilder on " << ctime(&now);
     1532                ElementNo = 0;
     1533                runner = elemente->start;
     1534                while (runner->next != elemente->end) { // go through every element
     1535                        runner = runner->next;
     1536                        if (ElementsInMolecule[runner->Z]) { // if this element got atoms
     1537                                ElementNo++;
     1538                                walker = start;
     1539                                while (walker->next != end) { // go through every atom of this element
     1540                                        walker = walker->next;
     1541                                        if (walker->type == runner) { // if this atom fits to element
     1542                                                walker->OutputXYZLine(out);
     1543                                        }
     1544                                }
     1545                        }
     1546                }
     1547                return true;
     1548        } else
     1549                return false;
    15501550};
    15511551
     
    15571557        int i = 0;
    15581558        atom *Walker = start;
    1559   while (Walker->next != end) {
    1560     Walker = Walker->next;
    1561     i++;
    1562   }
    1563   if ((AtomCount == 0) || (i != AtomCount)) {
    1564     *out << Verbose(3) << "Mismatch in AtomCount " << AtomCount << " and recounted number " << i << ", renaming all." << endl;
    1565         AtomCount = i;
    1566 
    1567     // count NonHydrogen atoms and give each atom a unique name
    1568     if (AtomCount != 0) {
    1569             i=0;
    1570             NoNonHydrogen = 0;
    1571       Walker = start;
    1572             while (Walker->next != end) {
    1573               Walker = Walker->next;
    1574               Walker->nr = i;  // update number in molecule (for easier referencing in FragmentMolecule lateron)
    1575               if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it
    1576                 NoNonHydrogen++;
    1577               Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name");
    1578               Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name");
    1579               sprintf(Walker->Name, "%2s%02d", Walker->type->symbol, Walker->nr+1);
    1580         *out << "Naming atom nr. " << Walker->nr << " " << Walker->Name << "." << endl;
    1581               i++;
    1582             }
    1583     } else
    1584         *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl;
    1585   }
     1559        while (Walker->next != end) {
     1560                Walker = Walker->next;
     1561                i++;
     1562        }
     1563        if ((AtomCount == 0) || (i != AtomCount)) {
     1564                *out << Verbose(3) << "Mismatch in AtomCount " << AtomCount << " and recounted number " << i << ", renaming all." << endl;
     1565                AtomCount = i;
     1566
     1567                // count NonHydrogen atoms and give each atom a unique name
     1568                if (AtomCount != 0) {
     1569                        i=0;
     1570                        NoNonHydrogen = 0;
     1571                        Walker = start;
     1572                        while (Walker->next != end) {
     1573                                Walker = Walker->next;
     1574                                Walker->nr = i; // update number in molecule (for easier referencing in FragmentMolecule lateron)
     1575                                if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it
     1576                                        NoNonHydrogen++;
     1577                                Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name");
     1578                                Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name");
     1579                                sprintf(Walker->Name, "%2s%02d", Walker->type->symbol, Walker->nr+1);
     1580                                *out << "Naming atom nr. " << Walker->nr << " " << Walker->Name << "." << endl;
     1581                                i++;
     1582                        }
     1583                } else
     1584                        *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl;
     1585        }
    15861586};
    15871587
     
    15911591{
    15921592        int i = 0;
    1593   for(i=MAX_ELEMENTS;i--;)
    1594         ElementsInMolecule[i] = 0;
     1593        for(i=MAX_ELEMENTS;i--;)
     1594                ElementsInMolecule[i] = 0;
    15951595        ElementCount = 0;
    15961596
    1597   atom *walker = start;
    1598   while (walker->next != end) {
    1599     walker = walker->next;
    1600     ElementsInMolecule[walker->type->Z]++;
    1601     i++;
    1602   }
    1603   for(i=MAX_ELEMENTS;i--;)
    1604         ElementCount += (ElementsInMolecule[i] != 0 ? 1 : 0);
     1597        atom *walker = start;
     1598        while (walker->next != end) {
     1599                walker = walker->next;
     1600                ElementsInMolecule[walker->type->Z]++;
     1601                i++;
     1602        }
     1603        for(i=MAX_ELEMENTS;i--;)
     1604                ElementCount += (ElementsInMolecule[i] != 0 ? 1 : 0);
    16051605};
    16061606
     
    16121612int molecule::CountCyclicBonds(ofstream *out)
    16131613{
    1614   int No = 0;
    1615   int *MinimumRingSize = NULL;
    1616   MoleculeLeafClass *Subgraphs = NULL;
    1617   class StackClass<bond *> *BackEdgeStack = NULL;
    1618   bond *Binder = first;
    1619   if ((Binder->next != last) && (Binder->next->Type == Undetermined)) {
    1620     *out << Verbose(0) << "No Depth-First-Search analysis performed so far, calling ..." << endl;
    1621     Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack);
    1622     while (Subgraphs->next != NULL) {
    1623       Subgraphs = Subgraphs->next;
    1624       delete(Subgraphs->previous);
    1625     }
    1626     delete(Subgraphs);
    1627     delete[](MinimumRingSize);
    1628   }
    1629   while(Binder->next != last) {
    1630     Binder = Binder->next;
    1631     if (Binder->Cyclic)
    1632       No++;
    1633   }
    1634   delete(BackEdgeStack);
    1635   return No;
     1614        int No = 0;
     1615        int *MinimumRingSize = NULL;
     1616        MoleculeLeafClass *Subgraphs = NULL;
     1617        class StackClass<bond *> *BackEdgeStack = NULL;
     1618        bond *Binder = first;
     1619        if ((Binder->next != last) && (Binder->next->Type == Undetermined)) {
     1620                *out << Verbose(0) << "No Depth-First-Search analysis performed so far, calling ..." << endl;
     1621                Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack);
     1622                while (Subgraphs->next != NULL) {
     1623                        Subgraphs = Subgraphs->next;
     1624                        delete(Subgraphs->previous);
     1625                }
     1626                delete(Subgraphs);
     1627                delete[](MinimumRingSize);
     1628        }
     1629        while(Binder->next != last) {
     1630                Binder = Binder->next;
     1631                if (Binder->Cyclic)
     1632                        No++;
     1633        }
     1634        delete(BackEdgeStack);
     1635        return No;
    16361636};
    16371637/** Returns Shading as a char string.
     
    16411641string molecule::GetColor(enum Shading color)
    16421642{
    1643   switch(color) {
    1644     case white:
    1645       return "white";
    1646       break;
    1647     case lightgray:
    1648       return "lightgray";
    1649       break;
    1650     case darkgray:
    1651       return "darkgray";
    1652       break;
    1653     case black:
    1654       return "black";
    1655       break;
    1656     default:
    1657       return "uncolored";
    1658       break;
    1659   };
     1643        switch(color) {
     1644                case white:
     1645                        return "white";
     1646                        break;
     1647                case lightgray:
     1648                        return "lightgray";
     1649                        break;
     1650                case darkgray:
     1651                        return "darkgray";
     1652                        break;
     1653                case black:
     1654                        return "black";
     1655                        break;
     1656                default:
     1657                        return "uncolored";
     1658                        break;
     1659        };
    16601660};
    16611661
     
    16661666void molecule::CalculateOrbitals(class config &configuration)
    16671667{
    1668   configuration.MaxPsiDouble = configuration.PsiMaxNoDown = configuration.PsiMaxNoUp = configuration.PsiType = 0;
    1669   for(int i=MAX_ELEMENTS;i--;) {
    1670     if (ElementsInMolecule[i] != 0) {
    1671       //cout << "CalculateOrbitals: " << elemente->FindElement(i)->name << " has a valence of " << (int)elemente->FindElement(i)->Valence << " and there are " << ElementsInMolecule[i] << " of it." << endl;
    1672       configuration.MaxPsiDouble += ElementsInMolecule[i]*((int)elemente->FindElement(i)->Valence);
    1673     }
    1674   }
    1675   configuration.PsiMaxNoDown = configuration.MaxPsiDouble/2 + (configuration.MaxPsiDouble % 2);
    1676   configuration.PsiMaxNoUp = configuration.MaxPsiDouble/2;
    1677   configuration.MaxPsiDouble /= 2;
    1678   configuration.PsiType = (configuration.PsiMaxNoDown == configuration.PsiMaxNoUp) ? 0 : 1;
    1679   if ((configuration.PsiType == 1) && (configuration.ProcPEPsi < 2)) {
    1680     configuration.ProcPEGamma /= 2;
    1681     configuration.ProcPEPsi *= 2;
    1682   } else {
    1683     configuration.ProcPEGamma *= configuration.ProcPEPsi;
    1684     configuration.ProcPEPsi = 1;
    1685   }
    1686   configuration.InitMaxMinStopStep = configuration.MaxMinStopStep = configuration.MaxPsiDouble;
     1668        configuration.MaxPsiDouble = configuration.PsiMaxNoDown = configuration.PsiMaxNoUp = configuration.PsiType = 0;
     1669        for(int i=MAX_ELEMENTS;i--;) {
     1670                if (ElementsInMolecule[i] != 0) {
     1671                        //cout << "CalculateOrbitals: " << elemente->FindElement(i)->name << " has a valence of " << (int)elemente->FindElement(i)->Valence << " and there are " << ElementsInMolecule[i] << " of it." << endl;
     1672                        configuration.MaxPsiDouble += ElementsInMolecule[i]*((int)elemente->FindElement(i)->Valence);
     1673                }
     1674        }
     1675        configuration.PsiMaxNoDown = configuration.MaxPsiDouble/2 + (configuration.MaxPsiDouble % 2);
     1676        configuration.PsiMaxNoUp = configuration.MaxPsiDouble/2;
     1677        configuration.MaxPsiDouble /= 2;
     1678        configuration.PsiType = (configuration.PsiMaxNoDown == configuration.PsiMaxNoUp) ? 0 : 1;
     1679        if ((configuration.PsiType == 1) && (configuration.ProcPEPsi < 2)) {
     1680                configuration.ProcPEGamma /= 2;
     1681                configuration.ProcPEPsi *= 2;
     1682        } else {
     1683                configuration.ProcPEGamma *= configuration.ProcPEPsi;
     1684                configuration.ProcPEPsi = 1;
     1685        }
     1686        configuration.InitMaxMinStopStep = configuration.MaxMinStopStep = configuration.MaxPsiDouble;
    16871687};
    16881688
     
    16971697                        atom *Walker, *OtherWalker;
    16981698
    1699                 if (!input)
    1700                 {
    1701                         cout << Verbose(1) << "Opening silica failed \n";
    1702                 };
     1699                                        if (!input)
     1700                                        {
     1701                                                cout << Verbose(1) << "Opening silica failed \n";
     1702                                        };
    17031703
    17041704                        *input >> ws >> atom1;
    17051705                        *input >> ws >> atom2;
    1706                 cout << Verbose(1) << "Scanning file\n";
    1707                 while (!input->eof()) // Check whether we read everything already
    1708                 {
     1706                                        cout << Verbose(1) << "Scanning file\n";
     1707                                        while (!input->eof()) // Check whether we read everything already
     1708                                        {
    17091709                                *input >> ws >> atom1;
    17101710                                *input >> ws >> atom2;
    1711                         if(atom2<atom1) //Sort indices of atoms in order
    1712                         {
    1713                                 temp=atom1;
    1714                                 atom1=atom2;
    1715                                 atom2=temp;
    1716                         };
    1717 
    1718                         Walker=start;
    1719                         while(Walker-> nr != atom1) // Find atom corresponding to first index
    1720                         {
    1721                                 Walker = Walker->next;
    1722                         };
    1723                         OtherWalker = Walker->next;
    1724                         while(OtherWalker->nr != atom2) // Find atom corresponding to second index
    1725                         {
    1726                                 OtherWalker= OtherWalker->next;
    1727                         };
    1728                         AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices.
    1729                        
    1730                 }
    1731 
    1732                 CreateListOfBondsPerAtom(out);
     1711                                                if(atom2<atom1) //Sort indices of atoms in order
     1712                                                {
     1713                                                        temp=atom1;
     1714                                                        atom1=atom2;
     1715                                                        atom2=temp;
     1716                                                };
     1717
     1718                                                Walker=start;
     1719                                                while(Walker-> nr != atom1) // Find atom corresponding to first index
     1720                                                {
     1721                                                        Walker = Walker->next;
     1722                                                };
     1723                                                OtherWalker = Walker->next;
     1724                                                while(OtherWalker->nr != atom2) // Find atom corresponding to second index
     1725                                                {
     1726                                                        OtherWalker= OtherWalker->next;
     1727                                                };
     1728                                                AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices.
     1729               
     1730                                        }
     1731
     1732                                        CreateListOfBondsPerAtom(out);
    17331733
    17341734};
     
    17411741 * To make it O(N log N) the function uses the linked-cell technique as follows:
    17421742 * The procedure is step-wise:
    1743  *  -# Remove every bond in list
    1744  *  -# Count the atoms in the molecule with CountAtoms()
    1745  *  -# partition cell into smaller linked cells of size \a bonddistance
    1746  *  -# put each atom into its corresponding cell
    1747  *  -# go through every cell, check the atoms therein against all possible bond partners in the 27 adjacent cells, add bond if true
    1748  *  -# create the list of bonds via CreateListOfBondsPerAtom()
    1749  *  -# correct the bond degree iteratively (single->double->triple bond)
    1750  *  -# finally print the bond list to \a *out if desired
     1743 *      -# Remove every bond in list
     1744 *      -# Count the atoms in the molecule with CountAtoms()
     1745 *      -# partition cell into smaller linked cells of size \a bonddistance
     1746 *      -# put each atom into its corresponding cell
     1747 *      -# go through every cell, check the atoms therein against all possible bond partners in the 27 adjacent cells, add bond if true
     1748 *      -# create the list of bonds via CreateListOfBondsPerAtom()
     1749 *      -# correct the bond degree iteratively (single->double->triple bond)
     1750 *      -# finally print the bond list to \a *out if desired
    17511751 * \param *out out stream for printing the matrix, NULL if no output
    17521752 * \param bonddistance length of linked cells (i.e. maximum minimal length checked)
     
    17561756{
    17571757
    1758   atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL;
    1759   int No, NoBonds, CandidateBondNo;
    1760   int NumberCells, divisor[NDIM], n[NDIM], N[NDIM], index, Index, j;
    1761   molecule **CellList;
    1762   double distance, MinDistance, MaxDistance;
    1763   double *matrix = ReturnFullMatrixforSymmetric(cell_size);
    1764   Vector x;
    1765   int FalseBondDegree = 0;
    1766 
    1767   BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem);
    1768   *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl;
    1769   // remove every bond from the list
    1770   if ((first->next != last) && (last->previous != first)) {  // there are bonds present
    1771     cleanup(first,last);
    1772   }
    1773 
    1774   // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering)
    1775   CountAtoms(out);
    1776   *out << Verbose(1) << "AtomCount " << AtomCount << "." << endl;
    1777 
    1778   if (AtomCount != 0) {
    1779     // 1. find divisor for each axis, such that a sphere with radius of at least bonddistance can be placed into each cell
    1780     j=-1;
    1781     for (int i=0;i<NDIM;i++) {
    1782       j += i+1;
    1783       divisor[i] = (int)floor(cell_size[j]/bonddistance); // take smaller value such that size of linked cell is at least bonddistance
    1784       //*out << Verbose(1) << "divisor[" << i << "]  = " << divisor[i] << "." << endl;
    1785     }
    1786     // 2a. allocate memory for the cell list
    1787     NumberCells = divisor[0]*divisor[1]*divisor[2];
    1788     *out << Verbose(1) << "Allocating " << NumberCells << " cells." << endl;
    1789     CellList = (molecule **) Malloc(sizeof(molecule *)*NumberCells, "molecule::CreateAdjacencyList - ** CellList");
    1790     for (int i=NumberCells;i--;)
    1791       CellList[i] = NULL;
    1792 
    1793     // 2b. put all atoms into its corresponding list
    1794     Walker = start;
    1795     while(Walker->next != end) {
    1796       Walker = Walker->next;
    1797       //*out << Verbose(1) << "Current atom is " << *Walker << " with coordinates ";
    1798       //Walker->x.Output(out);
    1799       //*out << "." << endl;
    1800       // compute the cell by the atom's coordinates
    1801       j=-1;
    1802       for (int i=0;i<NDIM;i++) {
    1803         j += i+1;
    1804         x.CopyVector(&(Walker->x));
    1805         x.KeepPeriodic(out, matrix);
    1806         n[i] = (int)floor(x.x[i]/cell_size[j]*(double)divisor[i]);
    1807       }
    1808       index = n[2] + (n[1] + n[0] * divisor[1]) * divisor[2];
    1809       //*out << Verbose(1) << "Atom " << *Walker << " goes into cell number [" << n[0] << "," << n[1] << "," << n[2] << "] = " << index << "." << endl;
    1810       // add copy atom to this cell
    1811       if (CellList[index] == NULL)  // allocate molecule if not done
    1812         CellList[index] = new molecule(elemente);
    1813       OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference
    1814       //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl;
    1815     }
    1816     //for (int i=0;i<NumberCells;i++)
    1817       //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl;
    1818 
    1819 
    1820     // 3a. go through every cell
    1821     for (N[0]=divisor[0];N[0]--;)
    1822       for (N[1]=divisor[1];N[1]--;)
    1823         for (N[2]=divisor[2];N[2]--;) {
    1824           Index = N[2] + (N[1] + N[0] * divisor[1]) * divisor[2];
    1825           if (CellList[Index] != NULL) { // if there atoms in this cell
    1826             //*out << Verbose(1) << "Current cell is " << Index << "." << endl;
    1827             // 3b. for every atom therein
    1828             Walker = CellList[Index]->start;
    1829             while (Walker->next != CellList[Index]->end) {  // go through every atom
    1830               Walker = Walker->next;
    1831               //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl;
    1832               // 3c. check for possible bond between each atom in this and every one in the 27 cells
    1833               for (n[0]=-1;n[0]<=1;n[0]++)
    1834                 for (n[1]=-1;n[1]<=1;n[1]++)
    1835                   for (n[2]=-1;n[2]<=1;n[2]++) {
    1836                      // compute the index of this comparison cell and make it periodic
    1837                     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];
    1838                     //*out << Verbose(1) << "Number of comparison cell is " << index << "." << endl;
    1839                     if (CellList[index] != NULL) {  // if there are any atoms in this cell
    1840                       OtherWalker = CellList[index]->start;
    1841                       while(OtherWalker->next != CellList[index]->end) {  // go through every atom in this cell
    1842                         OtherWalker = OtherWalker->next;
    1843                         //*out << Verbose(0) << "Current comparison atom is " << *OtherWalker << "." << endl;
    1844                         /// \todo periodic check is missing here!
    1845                         //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistance(&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl;
    1846                         MinDistance = OtherWalker->type->CovalentRadius + Walker->type->CovalentRadius;
    1847                         MinDistance *= (IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem;
    1848                         MaxDistance = MinDistance + BONDTHRESHOLD;
    1849                         MinDistance -= BONDTHRESHOLD;
    1850                         distance =   OtherWalker->x.PeriodicDistance(&(Walker->x), cell_size);
    1851                         if ((OtherWalker->father->nr > Walker->father->nr) && (distance <= MaxDistance*MaxDistance) && (distance >= MinDistance*MinDistance)) { // create bond if distance is smaller
    1852                           //*out << Verbose(0) << "Adding Bond between " << *Walker << " and " << *OtherWalker << "." << endl;
    1853                           AddBond(Walker->father, OtherWalker->father, 1);  // also increases molecule::BondCount
    1854                           BondCount++;
    1855                         } else {
    1856                           //*out << Verbose(1) << "Not Adding: Wrong label order or distance too great." << endl;
    1857                         }
    1858                       }
    1859                     }
    1860                   }
    1861             }
    1862           }
    1863         }
    1864 
    1865 
    1866 
    1867     // 4. free the cell again
    1868     for (int i=NumberCells;i--;)
    1869       if (CellList[i] != NULL) {
    1870         delete(CellList[i]);
    1871       }
    1872     Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList");
    1873 
    1874     // create the adjacency list per atom
    1875     CreateListOfBondsPerAtom(out);
    1876 
    1877     // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees,
    1878     // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene
    1879     // preferred over carbon bonds). Beforehand, we had picked the first mismatching partner, which lead to oxygenes with single instead of
    1880     // double bonds as was expected.
     1758        atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL;
     1759        int No, NoBonds, CandidateBondNo;
     1760        int NumberCells, divisor[NDIM], n[NDIM], N[NDIM], index, Index, j;
     1761        molecule **CellList;
     1762        double distance, MinDistance, MaxDistance;
     1763        double *matrix = ReturnFullMatrixforSymmetric(cell_size);
     1764        Vector x;
     1765        int FalseBondDegree = 0;
     1766
     1767        BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem);
     1768        *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl;
     1769        // remove every bond from the list
     1770        if ((first->next != last) && (last->previous != first)) {       // there are bonds present
     1771                cleanup(first,last);
     1772        }
     1773
     1774        // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering)
     1775        CountAtoms(out);
     1776        *out << Verbose(1) << "AtomCount " << AtomCount << "." << endl;
     1777
     1778        if (AtomCount != 0) {
     1779                // 1. find divisor for each axis, such that a sphere with radius of at least bonddistance can be placed into each cell
     1780                j=-1;
     1781                for (int i=0;i<NDIM;i++) {
     1782                        j += i+1;
     1783                        divisor[i] = (int)floor(cell_size[j]/bonddistance); // take smaller value such that size of linked cell is at least bonddistance
     1784                        //*out << Verbose(1) << "divisor[" << i << "]   = " << divisor[i] << "." << endl;
     1785                }
     1786                // 2a. allocate memory for the cell list
     1787                NumberCells = divisor[0]*divisor[1]*divisor[2];
     1788                *out << Verbose(1) << "Allocating " << NumberCells << " cells." << endl;
     1789                CellList = (molecule **) Malloc(sizeof(molecule *)*NumberCells, "molecule::CreateAdjacencyList - ** CellList");
     1790                for (int i=NumberCells;i--;)
     1791                        CellList[i] = NULL;
     1792
     1793                // 2b. put all atoms into its corresponding list
     1794                Walker = start;
     1795                while(Walker->next != end) {
     1796                        Walker = Walker->next;
     1797                        //*out << Verbose(1) << "Current atom is " << *Walker << " with coordinates ";
     1798                        //Walker->x.Output(out);
     1799                        //*out << "." << endl;
     1800                        // compute the cell by the atom's coordinates
     1801                        j=-1;
     1802                        for (int i=0;i<NDIM;i++) {
     1803                                j += i+1;
     1804                                x.CopyVector(&(Walker->x));
     1805                                x.KeepPeriodic(out, matrix);
     1806                                n[i] = (int)floor(x.x[i]/cell_size[j]*(double)divisor[i]);
     1807                        }
     1808                        index = n[2] + (n[1] + n[0] * divisor[1]) * divisor[2];
     1809                        //*out << Verbose(1) << "Atom " << *Walker << " goes into cell number [" << n[0] << "," << n[1] << "," << n[2] << "] = " << index << "." << endl;
     1810                        // add copy atom to this cell
     1811                        if (CellList[index] == NULL)    // allocate molecule if not done
     1812                                CellList[index] = new molecule(elemente);
     1813                        OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference
     1814                        //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl;
     1815                }
     1816                //for (int i=0;i<NumberCells;i++)
     1817                        //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl;
     1818
     1819
     1820                // 3a. go through every cell
     1821                for (N[0]=divisor[0];N[0]--;)
     1822                        for (N[1]=divisor[1];N[1]--;)
     1823                                for (N[2]=divisor[2];N[2]--;) {
     1824                                        Index = N[2] + (N[1] + N[0] * divisor[1]) * divisor[2];
     1825                                        if (CellList[Index] != NULL) { // if there atoms in this cell
     1826                                                //*out << Verbose(1) << "Current cell is " << Index << "." << endl;
     1827                                                // 3b. for every atom therein
     1828                                                Walker = CellList[Index]->start;
     1829                                                while (Walker->next != CellList[Index]->end) {  // go through every atom
     1830                                                        Walker = Walker->next;
     1831                                                        //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl;
     1832                                                        // 3c. check for possible bond between each atom in this and every one in the 27 cells
     1833                                                        for (n[0]=-1;n[0]<=1;n[0]++)
     1834                                                                for (n[1]=-1;n[1]<=1;n[1]++)
     1835                                                                        for (n[2]=-1;n[2]<=1;n[2]++) {
     1836                                                                                 // compute the index of this comparison cell and make it periodic
     1837                                                                                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];
     1838                                                                                //*out << Verbose(1) << "Number of comparison cell is " << index << "." << endl;
     1839                                                                                if (CellList[index] != NULL) {  // if there are any atoms in this cell
     1840                                                                                        OtherWalker = CellList[index]->start;
     1841                                                                                        while(OtherWalker->next != CellList[index]->end) {      // go through every atom in this cell
     1842                                                                                                OtherWalker = OtherWalker->next;
     1843                                                                                                //*out << Verbose(0) << "Current comparison atom is " << *OtherWalker << "." << endl;
     1844                                                                                                /// \todo periodic check is missing here!
     1845                                                                                                //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl;
     1846                                                                                                MinDistance = OtherWalker->type->CovalentRadius + Walker->type->CovalentRadius;
     1847                                                                                                MinDistance *= (IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem;
     1848                                                                                                MaxDistance = MinDistance + BONDTHRESHOLD;
     1849                                                                                                MinDistance -= BONDTHRESHOLD;
     1850                                                                                                distance = OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size);
     1851                                                                                                if ((OtherWalker->father->nr > Walker->father->nr) && (distance <= MaxDistance*MaxDistance) && (distance >= MinDistance*MinDistance)) { // create bond if distance is smaller
     1852                                                                                                        //*out << Verbose(1) << "Adding Bond between " << *Walker << " and " << *OtherWalker << " in distance " << sqrt(distance) << "." << endl;
     1853                                                                                                        AddBond(Walker->father, OtherWalker->father, 1);        // also increases molecule::BondCount
     1854                                                                                                } else {
     1855                                                                                                        //*out << Verbose(1) << "Not Adding: Wrong label order or distance too great." << endl;
     1856                                                                                                }
     1857                                                                                        }
     1858                                                                                }
     1859                                                                        }
     1860                                                }
     1861                                        }
     1862                                }
     1863
     1864
     1865
     1866                // 4. free the cell again
     1867                for (int i=NumberCells;i--;)
     1868                        if (CellList[i] != NULL) {
     1869                                delete(CellList[i]);
     1870                        }
     1871                Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList");
     1872
     1873                // create the adjacency list per atom
     1874                CreateListOfBondsPerAtom(out);
     1875
     1876                // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees,
     1877                // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene
     1878                // preferred over carbon bonds). Beforehand, we had picked the first mismatching partner, which lead to oxygenes with single instead of
     1879                // double bonds as was expected.
    18811880                if (BondCount != 0) {
    1882       NoCyclicBonds = 0;
    1883                   *out << Verbose(1) << "Correcting Bond degree of each bond ... ";
    1884                   do {
    1885                     No = 0; // No acts as breakup flag (if 1 we still continue)
    1886         Walker = start;
    1887         while (Walker->next != end) { // go through every atom
    1888           Walker = Walker->next;
    1889           // count valence of first partner
    1890           NoBonds = 0;
    1891           for(j=0;j<NumberOfBondsPerAtom[Walker->nr];j++)
    1892             NoBonds += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;
    1893           *out << Verbose(3) << "Walker " << *Walker << ": " << (int)Walker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;
    1894           if ((int)(Walker->type->NoValenceOrbitals) > NoBonds) { // we have a mismatch, check all bonding partners for mismatch
    1895             Candidate = NULL;
    1896             CandidateBondNo = -1;
    1897             for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through each of its bond partners
    1898               OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
    1899                     // count valence of second partner
    1900               NoBonds = 0;
    1901               for(j=0;j<NumberOfBondsPerAtom[OtherWalker->nr];j++)
    1902                 NoBonds += ListOfBondsPerAtom[OtherWalker->nr][j]->BondDegree;
    1903               *out << Verbose(3) << "OtherWalker " << *OtherWalker << ": " << (int)OtherWalker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;
    1904                     if ((int)(OtherWalker->type->NoValenceOrbitals) > NoBonds) { // check if possible candidate
    1905                       if ((Candidate == NULL) || (NumberOfBondsPerAtom[Candidate->nr] > NumberOfBondsPerAtom[OtherWalker->nr])) { // pick the one with fewer number of bonds first
    1906                   Candidate = OtherWalker;
    1907                   CandidateBondNo = i;
    1908                         *out << Verbose(3) << "New candidate is " << *Candidate << "." << endl;
    1909                       }
    1910                     }
    1911                   }
    1912             if ((Candidate != NULL) && (CandidateBondNo != -1)) {
    1913               ListOfBondsPerAtom[Walker->nr][CandidateBondNo]->BondDegree++;
    1914               *out << Verbose(2) << "Increased bond degree for bond " << *ListOfBondsPerAtom[Walker->nr][CandidateBondNo] << "." << endl;
    1915             } else
    1916               *out << Verbose(2) << "Could not find correct degree for atom " << *Walker << "." << endl;
    1917               FalseBondDegree++;
    1918           }
    1919                     }
    1920                   } while (No);
     1881                        NoCyclicBonds = 0;
     1882                        *out << Verbose(1) << "Correcting Bond degree of each bond ... ";
     1883                        do {
     1884                                No = 0; // No acts as breakup flag (if 1 we still continue)
     1885                                Walker = start;
     1886                                while (Walker->next != end) { // go through every atom
     1887                                        Walker = Walker->next;
     1888                                        // count valence of first partner
     1889                                        NoBonds = 0;
     1890                                        for(j=0;j<NumberOfBondsPerAtom[Walker->nr];j++)
     1891                                                NoBonds += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;
     1892                                        *out << Verbose(3) << "Walker " << *Walker << ": " << (int)Walker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;
     1893                                        if ((int)(Walker->type->NoValenceOrbitals) > NoBonds) { // we have a mismatch, check all bonding partners for mismatch
     1894                                                Candidate = NULL;
     1895                                                CandidateBondNo = -1;
     1896                                                for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through each of its bond partners
     1897                                                        OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
     1898                                                        // count valence of second partner
     1899                                                        NoBonds = 0;
     1900                                                        for(j=0;j<NumberOfBondsPerAtom[OtherWalker->nr];j++)
     1901                                                                NoBonds += ListOfBondsPerAtom[OtherWalker->nr][j]->BondDegree;
     1902                                                        *out << Verbose(3) << "OtherWalker " << *OtherWalker << ": " << (int)OtherWalker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;
     1903                                                        if ((int)(OtherWalker->type->NoValenceOrbitals) > NoBonds) { // check if possible candidate
     1904                                                                if ((Candidate == NULL) || (NumberOfBondsPerAtom[Candidate->nr] > NumberOfBondsPerAtom[OtherWalker->nr])) { // pick the one with fewer number of bonds first
     1905                                                                        Candidate = OtherWalker;
     1906                                                                        CandidateBondNo = i;
     1907                                                                        *out << Verbose(3) << "New candidate is " << *Candidate << "." << endl;
     1908                                                                }
     1909                                                        }
     1910                                                }
     1911                                                if ((Candidate != NULL) && (CandidateBondNo != -1)) {
     1912                                                        ListOfBondsPerAtom[Walker->nr][CandidateBondNo]->BondDegree++;
     1913                                                        *out << Verbose(2) << "Increased bond degree for bond " << *ListOfBondsPerAtom[Walker->nr][CandidateBondNo] << "." << endl;
     1914                                                } else
     1915                                                        *out << Verbose(2) << "Could not find correct degree for atom " << *Walker << "." << endl;
     1916                                                        FalseBondDegree++;
     1917                                        }
     1918                                }
     1919                        } while (No);
    19211920                *out << " done." << endl;
    19221921                } else
    19231922                        *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl;
    1924           *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl;
    1925 
    1926           // output bonds for debugging (if bond chain list was correctly installed)
    1927           *out << Verbose(1) << endl << "From contents of bond chain list:";
    1928           bond *Binder = first;
    1929     while(Binder->next != last) {
    1930       Binder = Binder->next;
     1923                *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl;
     1924
     1925                // output bonds for debugging (if bond chain list was correctly installed)
     1926                *out << Verbose(1) << endl << "From contents of bond chain list:";
     1927                bond *Binder = first;
     1928                while(Binder->next != last) {
     1929                        Binder = Binder->next;
    19311930                        *out << *Binder << "\t" << endl;
    1932     }
    1933     *out << endl;
    1934   } else
    1935         *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl;
    1936   *out << Verbose(0) << "End of CreateAdjacencyList." << endl;
    1937   Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix");
     1931                }
     1932                *out << endl;
     1933        } else
     1934                *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl;
     1935        *out << Verbose(0) << "End of CreateAdjacencyList." << endl;
     1936        Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix");
    19381937
    19391938};
     
    19511950MoleculeLeafClass * molecule::DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack)
    19521951{
    1953   class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);
    1954   BackEdgeStack = new StackClass<bond *> (BondCount);
    1955   MoleculeLeafClass *SubGraphs = new MoleculeLeafClass(NULL);
    1956   MoleculeLeafClass *LeafWalker = SubGraphs;
    1957   int CurrentGraphNr = 0, OldGraphNr;
    1958   int ComponentNumber = 0;
    1959   atom *Walker = NULL, *OtherAtom = NULL, *Root = start->next;
    1960   bond *Binder = NULL;
    1961   bool BackStepping = false;
    1962 
    1963   *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl;
    1964 
    1965   ResetAllBondsToUnused();
    1966   ResetAllAtomNumbers();
    1967   InitComponentNumbers();
    1968   BackEdgeStack->ClearStack();
    1969   while (Root != end) { // if there any atoms at all
    1970     // (1) mark all edges unused, empty stack, set atom->GraphNr = 0 for all
    1971     AtomStack->ClearStack();
    1972 
    1973     // put into new subgraph molecule and add this to list of subgraphs
    1974     LeafWalker = new MoleculeLeafClass(LeafWalker);
    1975     LeafWalker->Leaf = new molecule(elemente);
    1976     LeafWalker->Leaf->AddCopyAtom(Root);
    1977 
    1978     OldGraphNr = CurrentGraphNr;
    1979     Walker = Root;
    1980     do { // (10)
    1981       do { // (2) set number and Lowpoint of Atom to i, increase i, push current atom
    1982         if (!BackStepping) { // if we don't just return from (8)
    1983           Walker->GraphNr = CurrentGraphNr;
    1984           Walker->LowpointNr = CurrentGraphNr;
    1985           *out << Verbose(1) << "Setting Walker[" << Walker->Name << "]'s number to " << Walker->GraphNr << " with Lowpoint " << Walker->LowpointNr << "." << endl;
    1986           AtomStack->Push(Walker);
    1987           CurrentGraphNr++;
    1988         }
    1989         do { // (3) if Walker has no unused egdes, go to (5)
    1990           BackStepping = false; // reset backstepping flag for (8)
    1991           if (Binder == NULL) // if we don't just return from (11), Binder is already set to next unused
    1992             Binder = FindNextUnused(Walker);
    1993           if (Binder == NULL)
    1994             break;
    1995           *out << Verbose(2) << "Current Unused Bond is " << *Binder << "." << endl;
    1996           // (4) Mark Binder used, ...
    1997           Binder->MarkUsed(black);
    1998           OtherAtom = Binder->GetOtherAtom(Walker);
    1999           *out << Verbose(2) << "(4) OtherAtom is " << OtherAtom->Name << "." << endl;
    2000           if (OtherAtom->GraphNr != -1) {
    2001             // (4a) ... if "other" atom has been visited (GraphNr != 0), set lowpoint to minimum of both, go to (3)
    2002             Binder->Type = BackEdge;
    2003             BackEdgeStack->Push(Binder);
    2004             Walker->LowpointNr = ( Walker->LowpointNr < OtherAtom->GraphNr ) ? Walker->LowpointNr : OtherAtom->GraphNr;
    2005             *out << Verbose(3) << "(4a) Visited: Setting Lowpoint of Walker[" << Walker->Name << "] to " << Walker->LowpointNr << "." << endl;
    2006           } else {
    2007             // (4b) ... otherwise set OtherAtom as Ancestor of Walker and Walker as OtherAtom, go to (2)
    2008             Binder->Type = TreeEdge;
    2009             OtherAtom->Ancestor = Walker;
    2010             Walker = OtherAtom;
    2011             *out << Verbose(3) << "(4b) Not Visited: OtherAtom[" << OtherAtom->Name << "]'s Ancestor is now " << OtherAtom->Ancestor->Name << ", Walker is OtherAtom " << OtherAtom->Name << "." << endl;
    2012             break;
    2013           }
    2014           Binder = NULL;
    2015         } while (1);  // (3)
    2016         if (Binder == NULL) {
    2017           *out << Verbose(2) << "No more Unused Bonds." << endl;
    2018           break;
    2019         } else
    2020           Binder = NULL;
    2021       } while (1);  // (2)
    2022 
    2023       // 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!
    2024       if ((Walker == Root) && (Binder == NULL))
    2025         break;
    2026 
    2027       // (5) if Ancestor of Walker is ...
    2028       *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl;
    2029       if (Walker->Ancestor->GraphNr != Root->GraphNr) {
    2030         // (6)  (Ancestor of Walker is not Root)
    2031         if (Walker->LowpointNr < Walker->Ancestor->GraphNr) {
    2032           // (6a) set Ancestor's Lowpoint number to minimum of of its Ancestor and itself, go to Step(8)
    2033           Walker->Ancestor->LowpointNr = (Walker->Ancestor->LowpointNr < Walker->LowpointNr) ? Walker->Ancestor->LowpointNr : Walker->LowpointNr;
    2034           *out << Verbose(2) << "(6) Setting Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s Lowpoint to " << Walker->Ancestor->LowpointNr << "." << endl;
    2035         } else {
    2036           // (7) (Ancestor of Walker is a separating vertex, remove all from stack till Walker (including), these and Ancestor form a component
    2037           Walker->Ancestor->SeparationVertex = true;
    2038           *out << Verbose(2) << "(7) Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s is a separating vertex, creating component." << endl;
    2039           SetNextComponentNumber(Walker->Ancestor, ComponentNumber);
    2040           *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Ancestor's Compont is " << ComponentNumber << "." << endl;
    2041           SetNextComponentNumber(Walker, ComponentNumber);
    2042           *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Compont is " << ComponentNumber << "." << endl;
    2043           do {
    2044             OtherAtom = AtomStack->PopLast();
    2045             LeafWalker->Leaf->AddCopyAtom(OtherAtom);
    2046             SetNextComponentNumber(OtherAtom, ComponentNumber);
    2047             *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;
    2048           } while (OtherAtom != Walker);
    2049           ComponentNumber++;
    2050         }
    2051         // (8) Walker becomes its Ancestor, go to (3)
    2052         *out << Verbose(2) << "(8) Walker[" << Walker->Name << "] is now its Ancestor " << Walker->Ancestor->Name << ", backstepping. " << endl;
    2053         Walker = Walker->Ancestor;
    2054         BackStepping = true;
    2055       }
    2056       if (!BackStepping) {  // coming from (8) want to go to (3)
    2057         // (9) remove all from stack till Walker (including), these and Root form a component
    2058         AtomStack->Output(out);
    2059         SetNextComponentNumber(Root, ComponentNumber);
    2060         *out << Verbose(3) << "(9) Root[" << Root->Name << "]'s Component is " << ComponentNumber << "." << endl;
    2061         SetNextComponentNumber(Walker, ComponentNumber);
    2062         *out << Verbose(3) << "(9) Walker[" << Walker->Name << "]'s Component is " << ComponentNumber << "." << endl;
    2063         do {
    2064           OtherAtom = AtomStack->PopLast();
    2065           LeafWalker->Leaf->AddCopyAtom(OtherAtom);
    2066           SetNextComponentNumber(OtherAtom, ComponentNumber);
    2067           *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;
    2068         } while (OtherAtom != Walker);
    2069         ComponentNumber++;
    2070 
    2071         // (11) Root is separation vertex,  set Walker to Root and go to (4)
    2072         Walker = Root;
    2073         Binder = FindNextUnused(Walker);
    2074         *out << Verbose(1) << "(10) Walker is Root[" << Root->Name << "], next Unused Bond is " << Binder << "." << endl;
    2075         if (Binder != NULL) { // Root is separation vertex
    2076           *out << Verbose(1) << "(11) Root is a separation vertex." << endl;
    2077           Walker->SeparationVertex = true;
    2078         }
    2079       }
    2080     } while ((BackStepping) || (Binder != NULL)); // (10) halt only if Root has no unused edges
    2081 
    2082     // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph
    2083     *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl;
    2084     LeafWalker->Leaf->Output(out);
    2085     *out << endl;
    2086 
    2087     // step on to next root
    2088     while ((Root != end) && (Root->GraphNr != -1)) {
    2089       //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl;
    2090       if (Root->GraphNr != -1) // if already discovered, step on
    2091         Root = Root->next;
    2092     }
    2093   }
    2094   // set cyclic bond criterium on "same LP" basis
    2095   Binder = first;
    2096   while(Binder->next != last) {
    2097     Binder = Binder->next;
    2098     if (Binder->rightatom->LowpointNr == Binder->leftatom->LowpointNr) { // cyclic ??
    2099       Binder->Cyclic = true;
    2100       NoCyclicBonds++;
    2101     }
    2102   }
    2103 
    2104 
    2105   *out << Verbose(1) << "Final graph info for each atom is:" << endl;
    2106   Walker = start;
    2107   while (Walker->next != end) {
    2108     Walker = Walker->next;
    2109     *out << Verbose(2) << "Atom " << Walker->Name << " is " << ((Walker->SeparationVertex) ? "a" : "not a") << " separation vertex, components are ";
    2110     OutputComponentNumber(out, Walker);
    2111     *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl;
    2112   }
    2113 
    2114   *out << Verbose(1) << "Final graph info for each bond is:" << endl;
    2115   Binder = first;
    2116   while(Binder->next != last) {
    2117     Binder = Binder->next;
    2118     *out << Verbose(2) << ((Binder->Type == TreeEdge) ? "TreeEdge " : "BackEdge ") << *Binder << ": <";
    2119     *out << ((Binder->leftatom->SeparationVertex) ? "SP," : "") << "L" << Binder->leftatom->LowpointNr << " G" << Binder->leftatom->GraphNr << " Comp.";
    2120     OutputComponentNumber(out, Binder->leftatom);
    2121     *out << " ===  ";
    2122     *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp.";
    2123     OutputComponentNumber(out, Binder->rightatom);
    2124     *out << ">." << endl;
    2125     if (Binder->Cyclic) // cyclic ??
    2126       *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl;
    2127   }
    2128 
    2129   // free all and exit
    2130   delete(AtomStack);
    2131   *out << Verbose(0) << "End of DepthFirstSearchAnalysis" << endl;
    2132   return SubGraphs;
     1952        class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);
     1953        BackEdgeStack = new StackClass<bond *> (BondCount);
     1954        MoleculeLeafClass *SubGraphs = new MoleculeLeafClass(NULL);
     1955        MoleculeLeafClass *LeafWalker = SubGraphs;
     1956        int CurrentGraphNr = 0, OldGraphNr;
     1957        int ComponentNumber = 0;
     1958        atom *Walker = NULL, *OtherAtom = NULL, *Root = start->next;
     1959        bond *Binder = NULL;
     1960        bool BackStepping = false;
     1961
     1962        *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl;
     1963
     1964        ResetAllBondsToUnused();
     1965        ResetAllAtomNumbers();
     1966        InitComponentNumbers();
     1967        BackEdgeStack->ClearStack();
     1968        while (Root != end) { // if there any atoms at all
     1969                // (1) mark all edges unused, empty stack, set atom->GraphNr = 0 for all
     1970                AtomStack->ClearStack();
     1971
     1972                // put into new subgraph molecule and add this to list of subgraphs
     1973                LeafWalker = new MoleculeLeafClass(LeafWalker);
     1974                LeafWalker->Leaf = new molecule(elemente);
     1975                LeafWalker->Leaf->AddCopyAtom(Root);
     1976
     1977                OldGraphNr = CurrentGraphNr;
     1978                Walker = Root;
     1979                do { // (10)
     1980                        do { // (2) set number and Lowpoint of Atom to i, increase i, push current atom
     1981                                if (!BackStepping) { // if we don't just return from (8)
     1982                                        Walker->GraphNr = CurrentGraphNr;
     1983                                        Walker->LowpointNr = CurrentGraphNr;
     1984                                        *out << Verbose(1) << "Setting Walker[" << Walker->Name << "]'s number to " << Walker->GraphNr << " with Lowpoint " << Walker->LowpointNr << "." << endl;
     1985                                        AtomStack->Push(Walker);
     1986                                        CurrentGraphNr++;
     1987                                }
     1988                                do { // (3) if Walker has no unused egdes, go to (5)
     1989                                        BackStepping = false; // reset backstepping flag for (8)
     1990                                        if (Binder == NULL) // if we don't just return from (11), Binder is already set to next unused
     1991                                                Binder = FindNextUnused(Walker);
     1992                                        if (Binder == NULL)
     1993                                                break;
     1994                                        *out << Verbose(2) << "Current Unused Bond is " << *Binder << "." << endl;
     1995                                        // (4) Mark Binder used, ...
     1996                                        Binder->MarkUsed(black);
     1997                                        OtherAtom = Binder->GetOtherAtom(Walker);
     1998                                        *out << Verbose(2) << "(4) OtherAtom is " << OtherAtom->Name << "." << endl;
     1999                                        if (OtherAtom->GraphNr != -1) {
     2000                                                // (4a) ... if "other" atom has been visited (GraphNr != 0), set lowpoint to minimum of both, go to (3)
     2001                                                Binder->Type = BackEdge;
     2002                                                BackEdgeStack->Push(Binder);
     2003                                                Walker->LowpointNr = ( Walker->LowpointNr < OtherAtom->GraphNr ) ? Walker->LowpointNr : OtherAtom->GraphNr;
     2004                                                *out << Verbose(3) << "(4a) Visited: Setting Lowpoint of Walker[" << Walker->Name << "] to " << Walker->LowpointNr << "." << endl;
     2005                                        } else {
     2006                                                // (4b) ... otherwise set OtherAtom as Ancestor of Walker and Walker as OtherAtom, go to (2)
     2007                                                Binder->Type = TreeEdge;
     2008                                                OtherAtom->Ancestor = Walker;
     2009                                                Walker = OtherAtom;
     2010                                                *out << Verbose(3) << "(4b) Not Visited: OtherAtom[" << OtherAtom->Name << "]'s Ancestor is now " << OtherAtom->Ancestor->Name << ", Walker is OtherAtom " << OtherAtom->Name << "." << endl;
     2011                                                break;
     2012                                        }
     2013                                        Binder = NULL;
     2014                                } while (1);    // (3)
     2015                                if (Binder == NULL) {
     2016                                        *out << Verbose(2) << "No more Unused Bonds." << endl;
     2017                                        break;
     2018                                } else
     2019                                        Binder = NULL;
     2020                        } while (1);    // (2)
     2021
     2022                        // 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!
     2023                        if ((Walker == Root) && (Binder == NULL))
     2024                                break;
     2025
     2026                        // (5) if Ancestor of Walker is ...
     2027                        *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl;
     2028                        if (Walker->Ancestor->GraphNr != Root->GraphNr) {
     2029                                // (6)  (Ancestor of Walker is not Root)
     2030                                if (Walker->LowpointNr < Walker->Ancestor->GraphNr) {
     2031                                        // (6a) set Ancestor's Lowpoint number to minimum of of its Ancestor and itself, go to Step(8)
     2032                                        Walker->Ancestor->LowpointNr = (Walker->Ancestor->LowpointNr < Walker->LowpointNr) ? Walker->Ancestor->LowpointNr : Walker->LowpointNr;
     2033                                        *out << Verbose(2) << "(6) Setting Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s Lowpoint to " << Walker->Ancestor->LowpointNr << "." << endl;
     2034                                } else {
     2035                                        // (7) (Ancestor of Walker is a separating vertex, remove all from stack till Walker (including), these and Ancestor form a component
     2036                                        Walker->Ancestor->SeparationVertex = true;
     2037                                        *out << Verbose(2) << "(7) Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s is a separating vertex, creating component." << endl;
     2038                                        SetNextComponentNumber(Walker->Ancestor, ComponentNumber);
     2039                                        *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Ancestor's Compont is " << ComponentNumber << "." << endl;
     2040                                        SetNextComponentNumber(Walker, ComponentNumber);
     2041                                        *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Compont is " << ComponentNumber << "." << endl;
     2042                                        do {
     2043                                                OtherAtom = AtomStack->PopLast();
     2044                                                LeafWalker->Leaf->AddCopyAtom(OtherAtom);
     2045                                                SetNextComponentNumber(OtherAtom, ComponentNumber);
     2046                                                *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;
     2047                                        } while (OtherAtom != Walker);
     2048                                        ComponentNumber++;
     2049                                }
     2050                                // (8) Walker becomes its Ancestor, go to (3)
     2051                                *out << Verbose(2) << "(8) Walker[" << Walker->Name << "] is now its Ancestor " << Walker->Ancestor->Name << ", backstepping. " << endl;
     2052                                Walker = Walker->Ancestor;
     2053                                BackStepping = true;
     2054                        }
     2055                        if (!BackStepping) {    // coming from (8) want to go to (3)
     2056                                // (9) remove all from stack till Walker (including), these and Root form a component
     2057                                AtomStack->Output(out);
     2058                                SetNextComponentNumber(Root, ComponentNumber);
     2059                                *out << Verbose(3) << "(9) Root[" << Root->Name << "]'s Component is " << ComponentNumber << "." << endl;
     2060                                SetNextComponentNumber(Walker, ComponentNumber);
     2061                                *out << Verbose(3) << "(9) Walker[" << Walker->Name << "]'s Component is " << ComponentNumber << "." << endl;
     2062                                do {
     2063                                        OtherAtom = AtomStack->PopLast();
     2064                                        LeafWalker->Leaf->AddCopyAtom(OtherAtom);
     2065                                        SetNextComponentNumber(OtherAtom, ComponentNumber);
     2066                                        *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;
     2067                                } while (OtherAtom != Walker);
     2068                                ComponentNumber++;
     2069
     2070                                // (11) Root is separation vertex,      set Walker to Root and go to (4)
     2071                                Walker = Root;
     2072                                Binder = FindNextUnused(Walker);
     2073                                *out << Verbose(1) << "(10) Walker is Root[" << Root->Name << "], next Unused Bond is " << Binder << "." << endl;
     2074                                if (Binder != NULL) { // Root is separation vertex
     2075                                        *out << Verbose(1) << "(11) Root is a separation vertex." << endl;
     2076                                        Walker->SeparationVertex = true;
     2077                                }
     2078                        }
     2079                } while ((BackStepping) || (Binder != NULL)); // (10) halt only if Root has no unused edges
     2080
     2081                // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph
     2082                *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl;
     2083                LeafWalker->Leaf->Output(out);
     2084                *out << endl;
     2085
     2086                // step on to next root
     2087                while ((Root != end) && (Root->GraphNr != -1)) {
     2088                        //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl;
     2089                        if (Root->GraphNr != -1) // if already discovered, step on
     2090                                Root = Root->next;
     2091                }
     2092        }
     2093        // set cyclic bond criterium on "same LP" basis
     2094        Binder = first;
     2095        while(Binder->next != last) {
     2096                Binder = Binder->next;
     2097                if (Binder->rightatom->LowpointNr == Binder->leftatom->LowpointNr) { // cyclic ??
     2098                        Binder->Cyclic = true;
     2099                        NoCyclicBonds++;
     2100                }
     2101        }
     2102
     2103
     2104        *out << Verbose(1) << "Final graph info for each atom is:" << endl;
     2105        Walker = start;
     2106        while (Walker->next != end) {
     2107                Walker = Walker->next;
     2108                *out << Verbose(2) << "Atom " << Walker->Name << " is " << ((Walker->SeparationVertex) ? "a" : "not a") << " separation vertex, components are ";
     2109                OutputComponentNumber(out, Walker);
     2110                *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl;
     2111        }
     2112
     2113        *out << Verbose(1) << "Final graph info for each bond is:" << endl;
     2114        Binder = first;
     2115        while(Binder->next != last) {
     2116                Binder = Binder->next;
     2117                *out << Verbose(2) << ((Binder->Type == TreeEdge) ? "TreeEdge " : "BackEdge ") << *Binder << ": <";
     2118                *out << ((Binder->leftatom->SeparationVertex) ? "SP," : "") << "L" << Binder->leftatom->LowpointNr << " G" << Binder->leftatom->GraphNr << " Comp.";
     2119                OutputComponentNumber(out, Binder->leftatom);
     2120                *out << " ===   ";
     2121                *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp.";
     2122                OutputComponentNumber(out, Binder->rightatom);
     2123                *out << ">." << endl;
     2124                if (Binder->Cyclic) // cyclic ??
     2125                        *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl;
     2126        }
     2127
     2128        // free all and exit
     2129        delete(AtomStack);
     2130        *out << Verbose(0) << "End of DepthFirstSearchAnalysis" << endl;
     2131        return SubGraphs;
    21332132};
    21342133
     
    21432142 * \todo BFS from the not-same-LP to find back to starting point of tributary cycle over more than one bond
    21442143 */
    2145 void molecule::CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> *  BackEdgeStack, int *&MinimumRingSize)
    2146 {
    2147   atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CyclicStructureAnalysis: **PredecessorList");
    2148   int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList");
    2149   enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList");
    2150   class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount);  // will hold the current ring
    2151   class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount);  // contains all "touched" atoms (that need to be reset after BFS loop)
    2152   atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL;
    2153   bond *Binder = NULL, *BackEdge = NULL;
    2154   int RingSize, NumCycles, MinRingSize = -1;
    2155 
    2156   // initialise each vertex as white with no predecessor, empty queue, color Root lightgray
    2157   for (int i=AtomCount;i--;) {
    2158     PredecessorList[i] = NULL;
    2159     ShortestPathList[i] = -1;
    2160     ColorList[i] = white;
    2161   }
    2162 
    2163   *out << Verbose(1) << "Back edge list - ";
    2164   BackEdgeStack->Output(out);
    2165 
    2166   *out << Verbose(1) << "Analysing cycles ... " << endl;
    2167   NumCycles = 0;
    2168   while (!BackEdgeStack->IsEmpty()) {
    2169     BackEdge = BackEdgeStack->PopFirst();
    2170     // this is the target
    2171     Root = BackEdge->leftatom;
    2172     // this is the source point
    2173     Walker = BackEdge->rightatom;
    2174     ShortestPathList[Walker->nr] = 0;
    2175     BFSStack->ClearStack();  // start with empty BFS stack
    2176     BFSStack->Push(Walker);
    2177     TouchedStack->Push(Walker);
    2178     *out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;
    2179     OtherAtom = NULL;
    2180     do {  // look for Root
    2181       Walker = BFSStack->PopFirst();
    2182       *out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;
    2183       for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
    2184         Binder = ListOfBondsPerAtom[Walker->nr][i];
    2185         if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder)
    2186           OtherAtom = Binder->GetOtherAtom(Walker);
     2144void molecule::CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> *        BackEdgeStack, int *&MinimumRingSize)
     2145{
     2146        atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CyclicStructureAnalysis: **PredecessorList");
     2147        int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList");
     2148        enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList");
     2149        class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount);        // will hold the current ring
     2150        class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount);    // contains all "touched" atoms (that need to be reset after BFS loop)
     2151        atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL;
     2152        bond *Binder = NULL, *BackEdge = NULL;
     2153        int RingSize, NumCycles, MinRingSize = -1;
     2154
     2155        // initialise each vertex as white with no predecessor, empty queue, color Root lightgray
     2156        for (int i=AtomCount;i--;) {
     2157                PredecessorList[i] = NULL;
     2158                ShortestPathList[i] = -1;
     2159                ColorList[i] = white;
     2160        }
     2161
     2162        *out << Verbose(1) << "Back edge list - ";
     2163        BackEdgeStack->Output(out);
     2164
     2165        *out << Verbose(1) << "Analysing cycles ... " << endl;
     2166        NumCycles = 0;
     2167        while (!BackEdgeStack->IsEmpty()) {
     2168                BackEdge = BackEdgeStack->PopFirst();
     2169                // this is the target
     2170                Root = BackEdge->leftatom;
     2171                // this is the source point
     2172                Walker = BackEdge->rightatom;
     2173                ShortestPathList[Walker->nr] = 0;
     2174                BFSStack->ClearStack(); // start with empty BFS stack
     2175                BFSStack->Push(Walker);
     2176                TouchedStack->Push(Walker);
     2177                *out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;
     2178                OtherAtom = NULL;
     2179                do {    // look for Root
     2180                        Walker = BFSStack->PopFirst();
     2181                        *out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;
     2182                        for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
     2183                                Binder = ListOfBondsPerAtom[Walker->nr][i];
     2184                                if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder)
     2185                                        OtherAtom = Binder->GetOtherAtom(Walker);
    21872186#ifdef ADDHYDROGEN
    2188           if (OtherAtom->type->Z != 1) {
     2187                                        if (OtherAtom->type->Z != 1) {
    21892188#endif
    2190             *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
    2191             if (ColorList[OtherAtom->nr] == white) {
    2192               TouchedStack->Push(OtherAtom);
    2193               ColorList[OtherAtom->nr] = lightgray;
    2194               PredecessorList[OtherAtom->nr] = Walker;  // Walker is the predecessor
    2195               ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
    2196               *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;
    2197               //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance
    2198                 *out << Verbose(3) << "Putting OtherAtom into queue." << endl;
    2199                 BFSStack->Push(OtherAtom);
    2200               //}
    2201             } else {
    2202               *out << Verbose(3) << "Not Adding, has already been visited." << endl;
    2203             }
    2204             if (OtherAtom == Root)
    2205               break;
     2189                                                *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
     2190                                                if (ColorList[OtherAtom->nr] == white) {
     2191                                                        TouchedStack->Push(OtherAtom);
     2192                                                        ColorList[OtherAtom->nr] = lightgray;
     2193                                                        PredecessorList[OtherAtom->nr] = Walker;        // Walker is the predecessor
     2194                                                        ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
     2195                                                        *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;
     2196                                                        //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance
     2197                                                                *out << Verbose(3) << "Putting OtherAtom into queue." << endl;
     2198                                                                BFSStack->Push(OtherAtom);
     2199                                                        //}
     2200                                                } else {
     2201                                                        *out << Verbose(3) << "Not Adding, has already been visited." << endl;
     2202                                                }
     2203                                                if (OtherAtom == Root)
     2204                                                        break;
    22062205#ifdef ADDHYDROGEN
    2207           } else {
    2208             *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl;
    2209             ColorList[OtherAtom->nr] = black;
    2210           }
     2206                                        } else {
     2207                                                *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl;
     2208                                                ColorList[OtherAtom->nr] = black;
     2209                                        }
    22112210#endif
    2212         } else {
    2213           *out << Verbose(2) << "Bond " << *Binder << " not Visiting, is the back edge." << endl;
    2214         }
    2215       }
    2216       ColorList[Walker->nr] = black;
    2217       *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
    2218       if (OtherAtom == Root) { // if we have found the root, check whether this cycle wasn't already found beforehand
    2219         // step through predecessor list
    2220         while (OtherAtom != BackEdge->rightatom) {
    2221           if (!OtherAtom->GetTrueFather()->IsCyclic)  // if one bond in the loop is not marked as cyclic, we haven't found this cycle yet
    2222             break;
    2223           else
    2224             OtherAtom = PredecessorList[OtherAtom->nr];
    2225         }
    2226         if (OtherAtom == BackEdge->rightatom) { // if each atom in found cycle is cyclic, loop's been found before already
    2227           *out << Verbose(3) << "This cycle was already found before, skipping and removing seeker from search." << endl;\
    2228           do {
    2229             OtherAtom = TouchedStack->PopLast();
    2230             if (PredecessorList[OtherAtom->nr] == Walker) {
    2231               *out << Verbose(4) << "Removing " << *OtherAtom << " from lists and stacks." << endl;
    2232               PredecessorList[OtherAtom->nr] = NULL;
    2233               ShortestPathList[OtherAtom->nr] = -1;
    2234               ColorList[OtherAtom->nr] = white;
    2235               BFSStack->RemoveItem(OtherAtom);
    2236             }
    2237           } while ((!TouchedStack->IsEmpty()) && (PredecessorList[OtherAtom->nr] == NULL));
    2238           TouchedStack->Push(OtherAtom);  // last was wrongly popped
    2239           OtherAtom = BackEdge->rightatom; // set to not Root
    2240         } else
    2241           OtherAtom = Root;
    2242       }
    2243     } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr])));
    2244 
    2245     if (OtherAtom == Root) {
    2246       // now climb back the predecessor list and thus find the cycle members
    2247       NumCycles++;
    2248       RingSize = 1;
    2249       Root->GetTrueFather()->IsCyclic = true;
    2250       *out << Verbose(1) << "Found ring contains: ";
    2251       Walker = Root;
    2252       while (Walker != BackEdge->rightatom) {
    2253         *out << Walker->Name << " <-> ";
    2254         Walker = PredecessorList[Walker->nr];
    2255         Walker->GetTrueFather()->IsCyclic = true;
    2256         RingSize++;
    2257       }
    2258       *out << Walker->Name << "  with a length of " << RingSize << "." << endl << endl;
    2259       // walk through all and set MinimumRingSize
    2260       Walker = Root;
    2261       MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;
    2262       while (Walker != BackEdge->rightatom) {
    2263         Walker = PredecessorList[Walker->nr];
    2264         if (RingSize < MinimumRingSize[Walker->GetTrueFather()->nr])
    2265           MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;
    2266       }
    2267       if ((RingSize < MinRingSize) || (MinRingSize == -1))
    2268         MinRingSize = RingSize;
    2269     } else {
    2270       *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl;
    2271     }
    2272 
    2273     // now clean the lists
    2274     while (!TouchedStack->IsEmpty()){
    2275       Walker = TouchedStack->PopFirst();
    2276       PredecessorList[Walker->nr] = NULL;
    2277       ShortestPathList[Walker->nr] = -1;
    2278       ColorList[Walker->nr] = white;
    2279     }
    2280   }
    2281   if (MinRingSize != -1) {
    2282     // go over all atoms
    2283     Root = start;
    2284     while(Root->next != end) {
    2285       Root = Root->next;
    2286 
    2287       if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is
    2288         Walker = Root;
    2289         ShortestPathList[Walker->nr] = 0;
    2290         BFSStack->ClearStack();  // start with empty BFS stack
    2291         BFSStack->Push(Walker);
    2292         TouchedStack->Push(Walker);
    2293         //*out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;
    2294         OtherAtom = Walker;
    2295         while (OtherAtom != NULL) {  // look for Root
    2296           Walker = BFSStack->PopFirst();
    2297           //*out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;
    2298           for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
    2299             Binder = ListOfBondsPerAtom[Walker->nr][i];
    2300             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
    2301               OtherAtom = Binder->GetOtherAtom(Walker);
    2302               //*out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
    2303               if (ColorList[OtherAtom->nr] == white) {
    2304                 TouchedStack->Push(OtherAtom);
    2305                 ColorList[OtherAtom->nr] = lightgray;
    2306                 PredecessorList[OtherAtom->nr] = Walker;  // Walker is the predecessor
    2307                 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
    2308                 //*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;
    2309                 if (OtherAtom->GetTrueFather()->IsCyclic) { // if the other atom is connected to a ring
    2310                   MinimumRingSize[Root->GetTrueFather()->nr] = ShortestPathList[OtherAtom->nr]+MinimumRingSize[OtherAtom->GetTrueFather()->nr];
    2311                   OtherAtom = NULL; //break;
    2312                   break;
    2313                 } else
    2314                   BFSStack->Push(OtherAtom);
    2315               } else {
    2316                 //*out << Verbose(3) << "Not Adding, has already been visited." << endl;
    2317               }
    2318             } else {
    2319               //*out << Verbose(3) << "Not Visiting, is a back edge." << endl;
    2320             }
    2321           }
    2322           ColorList[Walker->nr] = black;
    2323           //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
    2324         }
    2325 
    2326         // now clean the lists
    2327         while (!TouchedStack->IsEmpty()){
    2328           Walker = TouchedStack->PopFirst();
    2329           PredecessorList[Walker->nr] = NULL;
    2330           ShortestPathList[Walker->nr] = -1;
    2331           ColorList[Walker->nr] = white;
    2332         }
    2333       }
    2334       *out << Verbose(1) << "Minimum ring size of " << *Root << " is " << MinimumRingSize[Root->GetTrueFather()->nr] << "." << endl;
    2335     }
    2336     *out << Verbose(1) << "Minimum ring size is " << MinRingSize << ", over " << NumCycles << " cycles total." << endl;
    2337   } else
    2338     *out << Verbose(1) << "No rings were detected in the molecular structure." << endl;
    2339 
    2340   Free((void **)&PredecessorList, "molecule::CyclicStructureAnalysis: **PredecessorList");
    2341   Free((void **)&ShortestPathList, "molecule::CyclicStructureAnalysis: **ShortestPathList");
    2342   Free((void **)&ColorList, "molecule::CyclicStructureAnalysis: **ColorList");
    2343   delete(BFSStack);
     2211                                } else {
     2212                                        *out << Verbose(2) << "Bond " << *Binder << " not Visiting, is the back edge." << endl;
     2213                                }
     2214                        }
     2215                        ColorList[Walker->nr] = black;
     2216                        *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
     2217                        if (OtherAtom == Root) { // if we have found the root, check whether this cycle wasn't already found beforehand
     2218                                // step through predecessor list
     2219                                while (OtherAtom != BackEdge->rightatom) {
     2220                                        if (!OtherAtom->GetTrueFather()->IsCyclic)      // if one bond in the loop is not marked as cyclic, we haven't found this cycle yet
     2221                                                break;
     2222                                        else
     2223                                                OtherAtom = PredecessorList[OtherAtom->nr];
     2224                                }
     2225                                if (OtherAtom == BackEdge->rightatom) { // if each atom in found cycle is cyclic, loop's been found before already
     2226                                        *out << Verbose(3) << "This cycle was already found before, skipping and removing seeker from search." << endl;\
     2227                                        do {
     2228                                                OtherAtom = TouchedStack->PopLast();
     2229                                                if (PredecessorList[OtherAtom->nr] == Walker) {
     2230                                                        *out << Verbose(4) << "Removing " << *OtherAtom << " from lists and stacks." << endl;
     2231                                                        PredecessorList[OtherAtom->nr] = NULL;
     2232                                                        ShortestPathList[OtherAtom->nr] = -1;
     2233                                                        ColorList[OtherAtom->nr] = white;
     2234                                                        BFSStack->RemoveItem(OtherAtom);
     2235                                                }
     2236                                        } while ((!TouchedStack->IsEmpty()) && (PredecessorList[OtherAtom->nr] == NULL));
     2237                                        TouchedStack->Push(OtherAtom);  // last was wrongly popped
     2238                                        OtherAtom = BackEdge->rightatom; // set to not Root
     2239                                } else
     2240                                        OtherAtom = Root;
     2241                        }
     2242                } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr])));
     2243
     2244                if (OtherAtom == Root) {
     2245                        // now climb back the predecessor list and thus find the cycle members
     2246                        NumCycles++;
     2247                        RingSize = 1;
     2248                        Root->GetTrueFather()->IsCyclic = true;
     2249                        *out << Verbose(1) << "Found ring contains: ";
     2250                        Walker = Root;
     2251                        while (Walker != BackEdge->rightatom) {
     2252                                *out << Walker->Name << " <-> ";
     2253                                Walker = PredecessorList[Walker->nr];
     2254                                Walker->GetTrueFather()->IsCyclic = true;
     2255                                RingSize++;
     2256                        }
     2257                        *out << Walker->Name << "       with a length of " << RingSize << "." << endl << endl;
     2258                        // walk through all and set MinimumRingSize
     2259                        Walker = Root;
     2260                        MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;
     2261                        while (Walker != BackEdge->rightatom) {
     2262                                Walker = PredecessorList[Walker->nr];
     2263                                if (RingSize < MinimumRingSize[Walker->GetTrueFather()->nr])
     2264                                        MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;
     2265                        }
     2266                        if ((RingSize < MinRingSize) || (MinRingSize == -1))
     2267                                MinRingSize = RingSize;
     2268                } else {
     2269                        *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl;
     2270                }
     2271
     2272                // now clean the lists
     2273                while (!TouchedStack->IsEmpty()){
     2274                        Walker = TouchedStack->PopFirst();
     2275                        PredecessorList[Walker->nr] = NULL;
     2276                        ShortestPathList[Walker->nr] = -1;
     2277                        ColorList[Walker->nr] = white;
     2278                }
     2279        }
     2280        if (MinRingSize != -1) {
     2281                // go over all atoms
     2282                Root = start;
     2283                while(Root->next != end) {
     2284                        Root = Root->next;
     2285
     2286                        if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is
     2287                                Walker = Root;
     2288                                ShortestPathList[Walker->nr] = 0;
     2289                                BFSStack->ClearStack(); // start with empty BFS stack
     2290                                BFSStack->Push(Walker);
     2291                                TouchedStack->Push(Walker);
     2292                                //*out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;
     2293                                OtherAtom = Walker;
     2294                                while (OtherAtom != NULL) {     // look for Root
     2295                                        Walker = BFSStack->PopFirst();
     2296                                        //*out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;
     2297                                        for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
     2298                                                Binder = ListOfBondsPerAtom[Walker->nr][i];
     2299                                                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
     2300                                                        OtherAtom = Binder->GetOtherAtom(Walker);
     2301                                                        //*out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
     2302                                                        if (ColorList[OtherAtom->nr] == white) {
     2303                                                                TouchedStack->Push(OtherAtom);
     2304                                                                ColorList[OtherAtom->nr] = lightgray;
     2305                                                                PredecessorList[OtherAtom->nr] = Walker;        // Walker is the predecessor
     2306                                                                ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
     2307                                                                //*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;
     2308                                                                if (OtherAtom->GetTrueFather()->IsCyclic) { // if the other atom is connected to a ring
     2309                                                                        MinimumRingSize[Root->GetTrueFather()->nr] = ShortestPathList[OtherAtom->nr]+MinimumRingSize[OtherAtom->GetTrueFather()->nr];
     2310                                                                        OtherAtom = NULL; //break;
     2311                                                                        break;
     2312                                                                } else
     2313                                                                        BFSStack->Push(OtherAtom);
     2314                                                        } else {
     2315                                                                //*out << Verbose(3) << "Not Adding, has already been visited." << endl;
     2316                                                        }
     2317                                                } else {
     2318                                                        //*out << Verbose(3) << "Not Visiting, is a back edge." << endl;
     2319                                                }
     2320                                        }
     2321                                        ColorList[Walker->nr] = black;
     2322                                        //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
     2323                                }
     2324
     2325                                // now clean the lists
     2326                                while (!TouchedStack->IsEmpty()){
     2327                                        Walker = TouchedStack->PopFirst();
     2328                                        PredecessorList[Walker->nr] = NULL;
     2329                                        ShortestPathList[Walker->nr] = -1;
     2330                                        ColorList[Walker->nr] = white;
     2331                                }
     2332                        }
     2333                        *out << Verbose(1) << "Minimum ring size of " << *Root << " is " << MinimumRingSize[Root->GetTrueFather()->nr] << "." << endl;
     2334                }
     2335                *out << Verbose(1) << "Minimum ring size is " << MinRingSize << ", over " << NumCycles << " cycles total." << endl;
     2336        } else
     2337                *out << Verbose(1) << "No rings were detected in the molecular structure." << endl;
     2338
     2339        Free((void **)&PredecessorList, "molecule::CyclicStructureAnalysis: **PredecessorList");
     2340        Free((void **)&ShortestPathList, "molecule::CyclicStructureAnalysis: **ShortestPathList");
     2341        Free((void **)&ColorList, "molecule::CyclicStructureAnalysis: **ColorList");
     2342        delete(BFSStack);
    23442343};
    23452344
     
    23512350void molecule::SetNextComponentNumber(atom *vertex, int nr)
    23522351{
    2353   int i=0;
    2354   if (vertex != NULL) {
    2355     for(;i<NumberOfBondsPerAtom[vertex->nr];i++) {
    2356       if (vertex->ComponentNr[i] == -1) {  // check if not yet used
    2357         vertex->ComponentNr[i] = nr;
    2358         break;
    2359       }
    2360       else if (vertex->ComponentNr[i] == nr) // if number is already present, don't add another time
    2361         break;  // breaking here will not cause error!
    2362     }
    2363     if (i == NumberOfBondsPerAtom[vertex->nr])
    2364       cerr << "Error: All Component entries are already occupied!" << endl;
    2365   } else
    2366       cerr << "Error: Given vertex is NULL!" << endl;
     2352        int i=0;
     2353        if (vertex != NULL) {
     2354                for(;i<NumberOfBondsPerAtom[vertex->nr];i++) {
     2355                        if (vertex->ComponentNr[i] == -1) {      // check if not yet used
     2356                                vertex->ComponentNr[i] = nr;
     2357                                break;
     2358                        }
     2359                        else if (vertex->ComponentNr[i] == nr) // if number is already present, don't add another time
     2360                                break;  // breaking here will not cause error!
     2361                }
     2362                if (i == NumberOfBondsPerAtom[vertex->nr])
     2363                        cerr << "Error: All Component entries are already occupied!" << endl;
     2364        } else
     2365                        cerr << "Error: Given vertex is NULL!" << endl;
    23672366};
    23682367
     
    23722371void molecule::OutputComponentNumber(ofstream *out, atom *vertex)
    23732372{
    2374   for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)
    2375     *out << vertex->ComponentNr[i] << "  ";
     2373        for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)
     2374                *out << vertex->ComponentNr[i] << "     ";
    23762375};
    23772376
     
    23802379void molecule::InitComponentNumbers()
    23812380{
    2382   atom *Walker = start;
    2383   while(Walker->next != end) {
    2384     Walker = Walker->next;
    2385     if (Walker->ComponentNr != NULL)
    2386       Free((void **)&Walker->ComponentNr, "molecule::InitComponentNumbers: **Walker->ComponentNr");
    2387     Walker->ComponentNr = (int *) Malloc(sizeof(int)*NumberOfBondsPerAtom[Walker->nr], "molecule::InitComponentNumbers: *Walker->ComponentNr");
    2388     for (int i=NumberOfBondsPerAtom[Walker->nr];i--;)
    2389       Walker->ComponentNr[i] = -1;
    2390   }
     2381        atom *Walker = start;
     2382        while(Walker->next != end) {
     2383                Walker = Walker->next;
     2384                if (Walker->ComponentNr != NULL)
     2385                        Free((void **)&Walker->ComponentNr, "molecule::InitComponentNumbers: **Walker->ComponentNr");
     2386                Walker->ComponentNr = (int *) Malloc(sizeof(int)*NumberOfBondsPerAtom[Walker->nr], "molecule::InitComponentNumbers: *Walker->ComponentNr");
     2387                for (int i=NumberOfBondsPerAtom[Walker->nr];i--;)
     2388                        Walker->ComponentNr[i] = -1;
     2389        }
    23912390};
    23922391
     
    23972396bond * molecule::FindNextUnused(atom *vertex)
    23982397{
    2399   for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)
    2400     if (ListOfBondsPerAtom[vertex->nr][i]->IsUsed() == white)
    2401       return(ListOfBondsPerAtom[vertex->nr][i]);
    2402   return NULL;
     2398        for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)
     2399                if (ListOfBondsPerAtom[vertex->nr][i]->IsUsed() == white)
     2400                        return(ListOfBondsPerAtom[vertex->nr][i]);
     2401        return NULL;
    24032402};
    24042403
     
    24082407void molecule::ResetAllBondsToUnused()
    24092408{
    2410   bond *Binder = first;
    2411   while (Binder->next != last) {
    2412     Binder = Binder->next;
    2413     Binder->ResetUsed();
    2414   }
     2409        bond *Binder = first;
     2410        while (Binder->next != last) {
     2411                Binder = Binder->next;
     2412                Binder->ResetUsed();
     2413        }
    24152414};
    24162415
     
    24192418void molecule::ResetAllAtomNumbers()
    24202419{
    2421   atom *Walker = start;
    2422   while (Walker->next != end) {
    2423     Walker = Walker->next;
    2424     Walker->GraphNr  = -1;
    2425   }
     2420        atom *Walker = start;
     2421        while (Walker->next != end) {
     2422                Walker = Walker->next;
     2423                Walker->GraphNr = -1;
     2424        }
    24262425};
    24272426
     
    24322431void OutputAlreadyVisited(ofstream *out, int *list)
    24332432{
    2434   *out << Verbose(4) << "Already Visited Bonds:\t";
    2435   for(int i=1;i<=list[0];i++) *out << Verbose(0) << list[i] << "  ";
    2436   *out << endl;
     2433        *out << Verbose(4) << "Already Visited Bonds:\t";
     2434        for(int i=1;i<=list[0];i++) *out << Verbose(0) << list[i] << "  ";
     2435        *out << endl;
    24372436};
    24382437
     
    24402439 * The upper limit is
    24412440 * \f[
    2442  *  n = N \cdot C^k
     2441 *      n = N \cdot C^k
    24432442 * \f]
    24442443 * where \f$C=2^c\f$ and c is the maximum bond degree over N number of atoms.
     
    24492448int molecule::GuesstimateFragmentCount(ofstream *out, int order)
    24502449{
    2451   int c = 0;
    2452   int FragmentCount;
    2453   // get maximum bond degree
    2454   atom *Walker = start;
    2455   while (Walker->next != end) {
    2456     Walker = Walker->next;
    2457     c = (NumberOfBondsPerAtom[Walker->nr] > c) ? NumberOfBondsPerAtom[Walker->nr] : c;
    2458   }
    2459   FragmentCount = NoNonHydrogen*(1 << (c*order));
    2460   *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl;
    2461   return FragmentCount;
     2450        int c = 0;
     2451        int FragmentCount;
     2452        // get maximum bond degree
     2453        atom *Walker = start;
     2454        while (Walker->next != end) {
     2455                Walker = Walker->next;
     2456                c = (NumberOfBondsPerAtom[Walker->nr] > c) ? NumberOfBondsPerAtom[Walker->nr] : c;
     2457        }
     2458        FragmentCount = NoNonHydrogen*(1 << (c*order));
     2459        *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl;
     2460        return FragmentCount;
    24622461};
    24632462
     
    24702469bool molecule::ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet)
    24712470{
    2472   stringstream line;
    2473   int AtomNr;
    2474   int status = 0;
    2475 
    2476   line.str(buffer);
    2477   while (!line.eof()) {
    2478     line >> AtomNr;
    2479     if ((AtomNr >= 0) && (AtomNr < AtomCount)) {
    2480       CurrentSet.insert(AtomNr);  // insert at end, hence in same order as in file!
    2481       status++;
    2482     } // else it's "-1" or else and thus must not be added
    2483   }
    2484   *out << Verbose(1) << "The scanned KeySet is ";
    2485   for(KeySet::iterator runner = CurrentSet.begin(); runner != CurrentSet.end(); runner++) {
    2486     *out << (*runner) << "\t";
    2487   }
    2488   *out << endl;
    2489   return (status != 0);
     2471        stringstream line;
     2472        int AtomNr;
     2473        int status = 0;
     2474
     2475        line.str(buffer);
     2476        while (!line.eof()) {
     2477                line >> AtomNr;
     2478                if ((AtomNr >= 0) && (AtomNr < AtomCount)) {
     2479                        CurrentSet.insert(AtomNr);      // insert at end, hence in same order as in file!
     2480                        status++;
     2481                } // else it's "-1" or else and thus must not be added
     2482        }
     2483        *out << Verbose(1) << "The scanned KeySet is ";
     2484        for(KeySet::iterator runner = CurrentSet.begin(); runner != CurrentSet.end(); runner++) {
     2485                *out << (*runner) << "\t";
     2486        }
     2487        *out << endl;
     2488        return (status != 0);
    24902489};
    24912490
     
    25022501bool molecule::ParseKeySetFile(ofstream *out, char *path, Graph *&FragmentList)
    25032502{
    2504   bool status = true;
    2505   ifstream InputFile;
    2506   stringstream line;
    2507   GraphTestPair testGraphInsert;
    2508   int NumberOfFragments = 0;
    2509   double TEFactor;
    2510   char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename");
    2511 
    2512   if (FragmentList == NULL) { // check list pointer
    2513     FragmentList = new Graph;
    2514   }
    2515 
    2516   // 1st pass: open file and read
    2517   *out << Verbose(1) << "Parsing the KeySet file ... " << endl;
    2518   sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, KEYSETFILE);
    2519   InputFile.open(filename);
    2520   if (InputFile != NULL) {
    2521     // each line represents a new fragment
    2522     char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - *buffer");
    2523     // 1. parse keysets and insert into temp. graph
    2524     while (!InputFile.eof()) {
    2525       InputFile.getline(buffer, MAXSTRINGSIZE);
    2526       KeySet CurrentSet;
    2527       if ((strlen(buffer) > 0) && (ScanBufferIntoKeySet(out, buffer, CurrentSet))) {  // if at least one valid atom was added, write config
    2528         testGraphInsert = FragmentList->insert(GraphPair (CurrentSet,pair<int,double>(NumberOfFragments++,1)));  // store fragment number and current factor
    2529         if (!testGraphInsert.second) {
    2530           cerr << "KeySet file must be corrupt as there are two equal key sets therein!" << endl;
    2531         }
    2532         //FragmentList->ListOfMolecules[NumberOfFragments++] = StoreFragmentFromKeySet(out, CurrentSet, IsAngstroem);
    2533       }
    2534     }
    2535     // 2. Free and done
    2536     InputFile.close();
    2537     InputFile.clear();
    2538     Free((void **)&buffer, "molecule::ParseKeySetFile - *buffer");
    2539     *out << Verbose(1) << "done." << endl;
    2540   } else {
    2541     *out << Verbose(1) << "File " << filename << " not found." << endl;
    2542     status = false;
    2543   }
    2544 
    2545   // 2nd pass: open TEFactors file and read
    2546   *out << Verbose(1) << "Parsing the TEFactors file ... " << endl;
    2547   sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, TEFACTORSFILE);
    2548   InputFile.open(filename);
    2549   if (InputFile != NULL) {
    2550     // 3. add found TEFactors to each keyset
    2551     NumberOfFragments = 0;
    2552     for(Graph::iterator runner = FragmentList->begin();runner != FragmentList->end(); runner++) {
    2553       if (!InputFile.eof()) {
    2554         InputFile >> TEFactor;
    2555         (*runner).second.second = TEFactor;
    2556         *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl;
    2557       } else {
    2558         status = false;
    2559         break;
    2560       }
    2561     }
    2562     // 4. Free and done
    2563     InputFile.close();
    2564     *out << Verbose(1) << "done." << endl;
    2565   } else {
    2566     *out << Verbose(1) << "File " << filename << " not found." << endl;
    2567     status = false;
    2568   }
    2569 
    2570   // free memory
    2571   Free((void **)&filename, "molecule::ParseKeySetFile - filename");
    2572 
    2573   return status;
     2503        bool status = true;
     2504        ifstream InputFile;
     2505        stringstream line;
     2506        GraphTestPair testGraphInsert;
     2507        int NumberOfFragments = 0;
     2508        double TEFactor;
     2509        char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename");
     2510
     2511        if (FragmentList == NULL) { // check list pointer
     2512                FragmentList = new Graph;
     2513        }
     2514
     2515        // 1st pass: open file and read
     2516        *out << Verbose(1) << "Parsing the KeySet file ... " << endl;
     2517        sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, KEYSETFILE);
     2518        InputFile.open(filename);
     2519        if (InputFile != NULL) {
     2520                // each line represents a new fragment
     2521                char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - *buffer");
     2522                // 1. parse keysets and insert into temp. graph
     2523                while (!InputFile.eof()) {
     2524                        InputFile.getline(buffer, MAXSTRINGSIZE);
     2525                        KeySet CurrentSet;
     2526                        if ((strlen(buffer) > 0) && (ScanBufferIntoKeySet(out, buffer, CurrentSet))) {  // if at least one valid atom was added, write config
     2527                                testGraphInsert = FragmentList->insert(GraphPair (CurrentSet,pair<int,double>(NumberOfFragments++,1))); // store fragment number and current factor
     2528                                if (!testGraphInsert.second) {
     2529                                        cerr << "KeySet file must be corrupt as there are two equal key sets therein!" << endl;
     2530                                }
     2531                                //FragmentList->ListOfMolecules[NumberOfFragments++] = StoreFragmentFromKeySet(out, CurrentSet, IsAngstroem);
     2532                        }
     2533                }
     2534                // 2. Free and done
     2535                InputFile.close();
     2536                InputFile.clear();
     2537                Free((void **)&buffer, "molecule::ParseKeySetFile - *buffer");
     2538                *out << Verbose(1) << "done." << endl;
     2539        } else {
     2540                *out << Verbose(1) << "File " << filename << " not found." << endl;
     2541                status = false;
     2542        }
     2543
     2544        // 2nd pass: open TEFactors file and read
     2545        *out << Verbose(1) << "Parsing the TEFactors file ... " << endl;
     2546        sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, TEFACTORSFILE);
     2547        InputFile.open(filename);
     2548        if (InputFile != NULL) {
     2549                // 3. add found TEFactors to each keyset
     2550                NumberOfFragments = 0;
     2551                for(Graph::iterator runner = FragmentList->begin();runner != FragmentList->end(); runner++) {
     2552                        if (!InputFile.eof()) {
     2553                                InputFile >> TEFactor;
     2554                                (*runner).second.second = TEFactor;
     2555                                *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl;
     2556                        } else {
     2557                                status = false;
     2558                                break;
     2559                        }
     2560                }
     2561                // 4. Free and done
     2562                InputFile.close();
     2563                *out << Verbose(1) << "done." << endl;
     2564        } else {
     2565                *out << Verbose(1) << "File " << filename << " not found." << endl;
     2566                status = false;
     2567        }
     2568
     2569        // free memory
     2570        Free((void **)&filename, "molecule::ParseKeySetFile - filename");
     2571
     2572        return status;
    25742573};
    25752574
     
    25822581bool molecule::StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path)
    25832582{
    2584   ofstream output;
    2585   bool status =  true;
    2586   string line;
    2587 
    2588   // open KeySet file
    2589   line = path;
    2590   line.append("/");
    2591   line += FRAGMENTPREFIX;
    2592   line += KEYSETFILE;
    2593   output.open(line.c_str(), ios::out);
    2594   *out << Verbose(1) << "Saving key sets of the total graph ... ";
    2595   if(output != NULL) {
    2596     for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) {
    2597       for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) {
    2598         if (sprinter != (*runner).first.begin())
    2599           output << "\t";
    2600         output << *sprinter;
    2601       }
    2602       output << endl;
    2603     }
    2604     *out << "done." << endl;
    2605   } else {
    2606     cerr << "Unable to open " << line << " for writing keysets!" << endl;
    2607     status = false;
    2608   }
    2609   output.close();
    2610   output.clear();
    2611 
    2612   // open TEFactors file
    2613   line = path;
    2614   line.append("/");
    2615   line += FRAGMENTPREFIX;
    2616   line += TEFACTORSFILE;
    2617   output.open(line.c_str(), ios::out);
    2618   *out << Verbose(1) << "Saving TEFactors of the total graph ... ";
    2619   if(output != NULL) {
    2620     for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++)
    2621       output << (*runner).second.second << endl;
    2622     *out << Verbose(1) << "done." << endl;
    2623   } else {
    2624     *out << Verbose(1) << "failed to open " << line << "." << endl;
    2625     status = false;
    2626   }
    2627   output.close();
    2628 
    2629   return status;
     2583        ofstream output;
     2584        bool status =   true;
     2585        string line;
     2586
     2587        // open KeySet file
     2588        line = path;
     2589        line.append("/");
     2590        line += FRAGMENTPREFIX;
     2591        line += KEYSETFILE;
     2592        output.open(line.c_str(), ios::out);
     2593        *out << Verbose(1) << "Saving key sets of the total graph ... ";
     2594        if(output != NULL) {
     2595                for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) {
     2596                        for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) {
     2597                                if (sprinter != (*runner).first.begin())
     2598                                        output << "\t";
     2599                                output << *sprinter;
     2600                        }
     2601                        output << endl;
     2602                }
     2603                *out << "done." << endl;
     2604        } else {
     2605                cerr << "Unable to open " << line << " for writing keysets!" << endl;
     2606                status = false;
     2607        }
     2608        output.close();
     2609        output.clear();
     2610
     2611        // open TEFactors file
     2612        line = path;
     2613        line.append("/");
     2614        line += FRAGMENTPREFIX;
     2615        line += TEFACTORSFILE;
     2616        output.open(line.c_str(), ios::out);
     2617        *out << Verbose(1) << "Saving TEFactors of the total graph ... ";
     2618        if(output != NULL) {
     2619                for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++)
     2620                        output << (*runner).second.second << endl;
     2621                *out << Verbose(1) << "done." << endl;
     2622        } else {
     2623                *out << Verbose(1) << "failed to open " << line << "." << endl;
     2624                status = false;
     2625        }
     2626        output.close();
     2627
     2628        return status;
    26302629};
    26312630
     
    26382637bool molecule::StoreAdjacencyToFile(ofstream *out, char *path)
    26392638{
    2640   ofstream AdjacencyFile;
    2641   atom *Walker = NULL;
    2642   stringstream line;
    2643   bool status = true;
    2644 
    2645   line << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;
    2646   AdjacencyFile.open(line.str().c_str(), ios::out);
    2647   *out << Verbose(1) << "Saving adjacency list ... ";
    2648   if (AdjacencyFile != NULL) {
    2649     Walker = start;
    2650     while(Walker->next != end) {
    2651       Walker = Walker->next;
    2652       AdjacencyFile << Walker->nr << "\t";
    2653       for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++)
    2654         AdjacencyFile << ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker)->nr << "\t";
    2655       AdjacencyFile << endl;
    2656     }
    2657     AdjacencyFile.close();
    2658     *out << Verbose(1) << "done." << endl;
    2659   } else {
    2660     *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;
    2661     status = false;
    2662   }
    2663 
    2664   return status;
     2639        ofstream AdjacencyFile;
     2640        atom *Walker = NULL;
     2641        stringstream line;
     2642        bool status = true;
     2643
     2644        line << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;
     2645        AdjacencyFile.open(line.str().c_str(), ios::out);
     2646        *out << Verbose(1) << "Saving adjacency list ... ";
     2647        if (AdjacencyFile != NULL) {
     2648                Walker = start;
     2649                while(Walker->next != end) {
     2650                        Walker = Walker->next;
     2651                        AdjacencyFile << Walker->nr << "\t";
     2652                        for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++)
     2653                                AdjacencyFile << ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker)->nr << "\t";
     2654                        AdjacencyFile << endl;
     2655                }
     2656                AdjacencyFile.close();
     2657                *out << Verbose(1) << "done." << endl;
     2658        } else {
     2659                *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;
     2660                status = false;
     2661        }
     2662
     2663        return status;
    26652664};
    26662665
     
    26732672bool molecule::CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms)
    26742673{
    2675   ifstream File;
    2676   stringstream filename;
    2677   bool status = true;
    2678   char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");
    2679 
    2680   filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;
    2681   File.open(filename.str().c_str(), ios::out);
    2682   *out << Verbose(1) << "Looking at bond structure stored in adjacency file and comparing to present one ... ";
    2683   if (File != NULL) {
    2684     // allocate storage structure
    2685     int NonMatchNumber = 0;  // will number of atoms with differing bond structure
    2686     int *CurrentBonds = (int *) Malloc(sizeof(int)*8, "molecule::CheckAdjacencyFileAgainstMolecule - CurrentBonds"); // contains parsed bonds of current atom
    2687     int CurrentBondsOfAtom;
    2688 
    2689     // Parse the file line by line and count the bonds
    2690     while (!File.eof()) {
    2691       File.getline(buffer, MAXSTRINGSIZE);
    2692       stringstream line;
    2693       line.str(buffer);
    2694       int AtomNr = -1;
    2695       line >> AtomNr;
    2696       CurrentBondsOfAtom = -1; // we count one too far due to line end
    2697       // parse into structure
    2698       if ((AtomNr >= 0) && (AtomNr < AtomCount)) {
    2699         while (!line.eof())
    2700           line >> CurrentBonds[ ++CurrentBondsOfAtom ];
    2701         // compare against present bonds
    2702         //cout << Verbose(2) << "Walker is " << *Walker << ", bond partners: ";
    2703         if (CurrentBondsOfAtom == NumberOfBondsPerAtom[AtomNr]) {
    2704           for(int i=0;i<NumberOfBondsPerAtom[AtomNr];i++) {
    2705             int id = ListOfBondsPerAtom[AtomNr][i]->GetOtherAtom(ListOfAtoms[AtomNr])->nr;
    2706             int j = 0;
    2707             for (;(j<CurrentBondsOfAtom) && (CurrentBonds[j++] != id);); // check against all parsed bonds
    2708             if (CurrentBonds[j-1] != id) { // no match ? Then mark in ListOfAtoms
    2709               ListOfAtoms[AtomNr] = NULL;
    2710               NonMatchNumber++;
    2711               status = false;
    2712               //out << "[" << id << "]\t";
    2713             } else {
    2714               //out << id << "\t";
    2715             }
    2716           }
    2717           //out << endl;
    2718         } else {
    2719           *out << "Number of bonds for Atom " << *ListOfAtoms[AtomNr] << " does not match, parsed " << CurrentBondsOfAtom << " against " << NumberOfBondsPerAtom[AtomNr] << "." << endl;
    2720           status = false;
    2721         }
    2722       }
    2723     }
    2724     File.close();
    2725     File.clear();
    2726     if (status) { // if equal we parse the KeySetFile
    2727       *out << Verbose(1) << "done: Equal." << endl;
    2728       status = true;
    2729     } else
    2730       *out << Verbose(1) << "done: Not equal by " << NonMatchNumber << " atoms." << endl;
    2731     Free((void **)&CurrentBonds, "molecule::CheckAdjacencyFileAgainstMolecule - **CurrentBonds");
    2732   } else {
    2733     *out << Verbose(1) << "Adjacency file not found." << endl;
    2734     status = false;
    2735   }
    2736   *out << endl;
    2737   Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");
    2738 
    2739   return status;
     2674        ifstream File;
     2675        stringstream filename;
     2676        bool status = true;
     2677        char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");
     2678
     2679        filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;
     2680        File.open(filename.str().c_str(), ios::out);
     2681        *out << Verbose(1) << "Looking at bond structure stored in adjacency file and comparing to present one ... ";
     2682        if (File != NULL) {
     2683                // allocate storage structure
     2684                int NonMatchNumber = 0; // will number of atoms with differing bond structure
     2685                int *CurrentBonds = (int *) Malloc(sizeof(int)*8, "molecule::CheckAdjacencyFileAgainstMolecule - CurrentBonds"); // contains parsed bonds of current atom
     2686                int CurrentBondsOfAtom;
     2687
     2688                // Parse the file line by line and count the bonds
     2689                while (!File.eof()) {
     2690                        File.getline(buffer, MAXSTRINGSIZE);
     2691                        stringstream line;
     2692                        line.str(buffer);
     2693                        int AtomNr = -1;
     2694                        line >> AtomNr;
     2695                        CurrentBondsOfAtom = -1; // we count one too far due to line end
     2696                        // parse into structure
     2697                        if ((AtomNr >= 0) && (AtomNr < AtomCount)) {
     2698                                while (!line.eof())
     2699                                        line >> CurrentBonds[ ++CurrentBondsOfAtom ];
     2700                                // compare against present bonds
     2701                                //cout << Verbose(2) << "Walker is " << *Walker << ", bond partners: ";
     2702                                if (CurrentBondsOfAtom == NumberOfBondsPerAtom[AtomNr]) {
     2703                                        for(int i=0;i<NumberOfBondsPerAtom[AtomNr];i++) {
     2704                                                int id = ListOfBondsPerAtom[AtomNr][i]->GetOtherAtom(ListOfAtoms[AtomNr])->nr;
     2705                                                int j = 0;
     2706                                                for (;(j<CurrentBondsOfAtom) && (CurrentBonds[j++] != id);); // check against all parsed bonds
     2707                                                if (CurrentBonds[j-1] != id) { // no match ? Then mark in ListOfAtoms
     2708                                                        ListOfAtoms[AtomNr] = NULL;
     2709                                                        NonMatchNumber++;
     2710                                                        status = false;
     2711                                                        //out << "[" << id << "]\t";
     2712                                                } else {
     2713                                                        //out << id << "\t";
     2714                                                }
     2715                                        }
     2716                                        //out << endl;
     2717                                } else {
     2718                                        *out << "Number of bonds for Atom " << *ListOfAtoms[AtomNr] << " does not match, parsed " << CurrentBondsOfAtom << " against " << NumberOfBondsPerAtom[AtomNr] << "." << endl;
     2719                                        status = false;
     2720                                }
     2721                        }
     2722                }
     2723                File.close();
     2724                File.clear();
     2725                if (status) { // if equal we parse the KeySetFile
     2726                        *out << Verbose(1) << "done: Equal." << endl;
     2727                        status = true;
     2728                } else
     2729                        *out << Verbose(1) << "done: Not equal by " << NonMatchNumber << " atoms." << endl;
     2730                Free((void **)&CurrentBonds, "molecule::CheckAdjacencyFileAgainstMolecule - **CurrentBonds");
     2731        } else {
     2732                *out << Verbose(1) << "Adjacency file not found." << endl;
     2733                status = false;
     2734        }
     2735        *out << endl;
     2736        Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");
     2737
     2738        return status;
    27402739};
    27412740
     
    27512750bool molecule::CheckOrderAtSite(ofstream *out, bool *AtomMask, Graph *GlobalKeySetList, int Order, int *MinimumRingSize, char *path)
    27522751{
    2753   atom *Walker = start;
    2754   bool status = false;
    2755   ifstream InputFile;
    2756 
    2757   // initialize mask list
    2758   for(int i=AtomCount;i--;)
    2759     AtomMask[i] = false;
    2760 
    2761   if (Order < 0) { // adaptive increase of BondOrder per site
    2762     if (AtomMask[AtomCount] == true)  // break after one step
    2763       return false;
    2764     // parse the EnergyPerFragment file
    2765     char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckOrderAtSite: *buffer");
    2766     sprintf(buffer, "%s/%s%s.dat", path, FRAGMENTPREFIX, ENERGYPERFRAGMENT);
    2767     InputFile.open(buffer, ios::in);
    2768     if ((InputFile != NULL) && (GlobalKeySetList != NULL)) {
    2769       // transmorph graph keyset list into indexed KeySetList
    2770       map<int,KeySet> IndexKeySetList;
    2771       for(Graph::iterator runner = GlobalKeySetList->begin(); runner != GlobalKeySetList->end(); runner++) {
    2772         IndexKeySetList.insert( pair<int,KeySet>(runner->second.first,runner->first) );
    2773       }
    2774       int lines = 0;
    2775       // count the number of lines, i.e. the number of fragments
    2776       InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines
    2777       InputFile.getline(buffer, MAXSTRINGSIZE);
    2778       while(!InputFile.eof()) {
    2779         InputFile.getline(buffer, MAXSTRINGSIZE);
    2780         lines++;
    2781       }
    2782       //*out << Verbose(2) << "Scanned " << lines-1 << " lines." << endl;  // one endline too much
    2783       InputFile.clear();
    2784       InputFile.seekg(ios::beg);
    2785       map<int, pair<double,int> > AdaptiveCriteriaList;  // (Root No., (Value, Order)) !
    2786       int No, FragOrder;
    2787       double Value;
    2788       // each line represents a fragment root (Atom::nr) id and its energy contribution
    2789       InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines
    2790       InputFile.getline(buffer, MAXSTRINGSIZE);
    2791       while(!InputFile.eof()) {
    2792         InputFile.getline(buffer, MAXSTRINGSIZE);
    2793         if (strlen(buffer) > 2) {
    2794           //*out << Verbose(2) << "Scanning: " << buffer << endl;
    2795           stringstream line(buffer);
    2796           line >> FragOrder;
    2797           line >> ws >> No;
    2798           line >> ws >> Value; // skip time entry
    2799           line >> ws >> Value;
    2800           No -= 1;  // indices start at 1 in file, not 0
    2801           //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl;
    2802 
    2803           // clean the list of those entries that have been superceded by higher order terms already
    2804           map<int,KeySet>::iterator marker = IndexKeySetList.find(No);    // find keyset to Frag No.
    2805           if (marker != IndexKeySetList.end()) {  // if found
    2806             Value *= 1 + MYEPSILON*(*((*marker).second.begin()));    // in case of equal energies this makes em not equal without changing anything actually
    2807             // 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
    2808             pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) ));
    2809             map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first;
    2810             if (!InsertedElement.second) { // this root is already present
    2811               if ((*PresentItem).second.second < FragOrder)  // if order there is lower, update entry with higher-order term
    2812                 //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)
    2813                 {  // if value is smaller, update value and order
    2814                 (*PresentItem).second.first = fabs(Value);
    2815                 (*PresentItem).second.second = FragOrder;
    2816                 *out << Verbose(2) << "Updated element (" <<  (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;
    2817               } else {
    2818                 *out << Verbose(2) << "Did not update element " <<  (*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl;
    2819               }
    2820             } else {
    2821               *out << Verbose(2) << "Inserted element (" <<  (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;
    2822             }
    2823           } else {
    2824             *out << Verbose(1) << "No Fragment under No. " << No << "found." << endl;
    2825           }
    2826         }
    2827       }
    2828       // then map back onto (Value, (Root Nr., Order)) (i.e. sorted by value to pick the highest ones)
    2829       map<double, pair<int,int> > FinalRootCandidates;
    2830       *out << Verbose(1) << "Root candidate list is: " << endl;
    2831       for(map<int, pair<double,int> >::iterator runner = AdaptiveCriteriaList.begin(); runner != AdaptiveCriteriaList.end(); runner++) {
    2832         Walker = FindAtom((*runner).first);
    2833         if (Walker != NULL) {
    2834           //if ((*runner).second.second >= Walker->AdaptiveOrder) { // only insert if this is an "active" root site for the current order
    2835           if (!Walker->MaxOrder) {
    2836             *out << Verbose(2) << "(" << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "])" << endl;
    2837             FinalRootCandidates.insert( make_pair( (*runner).second.first, pair<int,int>((*runner).first, (*runner).second.second) ) );
    2838           } else {
    2839             *out << Verbose(2) << "Excluding (" << *Walker << ", " << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "]), as it has reached its maximum order." << endl;
    2840           }
    2841         } else {
    2842           cerr << "Atom No. " << (*runner).second.first << " was not found in this molecule." << endl;
    2843         }
    2844       }
    2845       // pick the ones still below threshold and mark as to be adaptively updated
    2846       for(map<double, pair<int,int> >::iterator runner = FinalRootCandidates.upper_bound(pow(10.,Order)); runner != FinalRootCandidates.end(); runner++) {
    2847         No = (*runner).second.first;
    2848         Walker = FindAtom(No);
    2849         //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) {
    2850           *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl;
    2851           AtomMask[No] = true;
    2852           status = true;
    2853         //} else
    2854           //*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;
    2855       }
    2856       // close and done
    2857       InputFile.close();
    2858       InputFile.clear();
    2859     } else {
    2860       cerr << "Unable to parse " << buffer << " file, incrementing all." << endl;
    2861       while (Walker->next != end) {
    2862         Walker = Walker->next;
    2863     #ifdef ADDHYDROGEN
    2864         if (Walker->type->Z != 1) // skip hydrogen
    2865     #endif
    2866         {
    2867           AtomMask[Walker->nr] = true;  // include all (non-hydrogen) atoms
    2868           status = true;
    2869         }
    2870       }
    2871     }
    2872     Free((void **)&buffer, "molecule::CheckOrderAtSite: *buffer");
    2873     // pick a given number of highest values and set AtomMask
    2874   } else { // global increase of Bond Order
    2875     while (Walker->next != end) {
    2876       Walker = Walker->next;
    2877   #ifdef ADDHYDROGEN
    2878       if (Walker->type->Z != 1) // skip hydrogen
    2879   #endif
    2880       {
    2881         AtomMask[Walker->nr] = true;  // include all (non-hydrogen) atoms
    2882         if ((Order != 0) && (Walker->AdaptiveOrder < Order)) // && (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]))
    2883           status = true;
    2884       }
    2885     }
    2886     if ((Order == 0) && (AtomMask[AtomCount] == false))  // single stepping, just check
    2887       status = true;
    2888 
    2889     if (!status) {
    2890       if (Order == 0)
    2891         *out << Verbose(1) << "Single stepping done." << endl;
    2892       else
    2893         *out << Verbose(1) << "Order at every site is already equal or above desired order " << Order << "." << endl;
    2894     }
    2895   }
    2896 
    2897   // print atom mask for debugging
    2898   *out << "              ";
    2899   for(int i=0;i<AtomCount;i++)
    2900     *out << (i % 10);
    2901   *out << endl << "Atom mask is: ";
    2902   for(int i=0;i<AtomCount;i++)
    2903     *out << (AtomMask[i] ? "t" : "f");
    2904   *out << endl;
    2905 
    2906   return status;
     2752        atom *Walker = start;
     2753        bool status = false;
     2754        ifstream InputFile;
     2755
     2756        // initialize mask list
     2757        for(int i=AtomCount;i--;)
     2758                AtomMask[i] = false;
     2759
     2760        if (Order < 0) { // adaptive increase of BondOrder per site
     2761                if (AtomMask[AtomCount] == true)        // break after one step
     2762                        return false;
     2763                // parse the EnergyPerFragment file
     2764                char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckOrderAtSite: *buffer");
     2765                sprintf(buffer, "%s/%s%s.dat", path, FRAGMENTPREFIX, ENERGYPERFRAGMENT);
     2766                InputFile.open(buffer, ios::in);
     2767                if ((InputFile != NULL) && (GlobalKeySetList != NULL)) {
     2768                        // transmorph graph keyset list into indexed KeySetList
     2769                        map<int,KeySet> IndexKeySetList;
     2770                        for(Graph::iterator runner = GlobalKeySetList->begin(); runner != GlobalKeySetList->end(); runner++) {
     2771                                IndexKeySetList.insert( pair<int,KeySet>(runner->second.first,runner->first) );
     2772                        }
     2773                        int lines = 0;
     2774                        // count the number of lines, i.e. the number of fragments
     2775                        InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines
     2776                        InputFile.getline(buffer, MAXSTRINGSIZE);
     2777                        while(!InputFile.eof()) {
     2778                                InputFile.getline(buffer, MAXSTRINGSIZE);
     2779                                lines++;
     2780                        }
     2781                        //*out << Verbose(2) << "Scanned " << lines-1 << " lines." << endl;      // one endline too much
     2782                        InputFile.clear();
     2783                        InputFile.seekg(ios::beg);
     2784                        map<int, pair<double,int> > AdaptiveCriteriaList;       // (Root No., (Value, Order)) !
     2785                        int No, FragOrder;
     2786                        double Value;
     2787                        // each line represents a fragment root (Atom::nr) id and its energy contribution
     2788                        InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines
     2789                        InputFile.getline(buffer, MAXSTRINGSIZE);
     2790                        while(!InputFile.eof()) {
     2791                                InputFile.getline(buffer, MAXSTRINGSIZE);
     2792                                if (strlen(buffer) > 2) {
     2793                                        //*out << Verbose(2) << "Scanning: " << buffer << endl;
     2794                                        stringstream line(buffer);
     2795                                        line >> FragOrder;
     2796                                        line >> ws >> No;
     2797                                        line >> ws >> Value; // skip time entry
     2798                                        line >> ws >> Value;
     2799                                        No -= 1;        // indices start at 1 in file, not 0
     2800                                        //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl;
     2801
     2802                                        // clean the list of those entries that have been superceded by higher order terms already
     2803                                        map<int,KeySet>::iterator marker = IndexKeySetList.find(No);            // find keyset to Frag No.
     2804                                        if (marker != IndexKeySetList.end()) {  // if found
     2805                                                Value *= 1 + MYEPSILON*(*((*marker).second.begin()));            // in case of equal energies this makes em not equal without changing anything actually
     2806                                                // 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
     2807                                                pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) ));
     2808                                                map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first;
     2809                                                if (!InsertedElement.second) { // this root is already present
     2810                                                        if ((*PresentItem).second.second < FragOrder)   // if order there is lower, update entry with higher-order term
     2811                                                                //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)
     2812                                                                {       // if value is smaller, update value and order
     2813                                                                (*PresentItem).second.first = fabs(Value);
     2814                                                                (*PresentItem).second.second = FragOrder;
     2815                                                                *out << Verbose(2) << "Updated element (" <<    (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;
     2816                                                        } else {
     2817                                                                *out << Verbose(2) << "Did not update element " <<      (*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl;
     2818                                                        }
     2819                                                } else {
     2820                                                        *out << Verbose(2) << "Inserted element (" <<   (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;
     2821                                                }
     2822                                        } else {
     2823                                                *out << Verbose(1) << "No Fragment under No. " << No << "found." << endl;
     2824                                        }
     2825                                }
     2826                        }
     2827                        // then map back onto (Value, (Root Nr., Order)) (i.e. sorted by value to pick the highest ones)
     2828                        map<double, pair<int,int> > FinalRootCandidates;
     2829                        *out << Verbose(1) << "Root candidate list is: " << endl;
     2830                        for(map<int, pair<double,int> >::iterator runner = AdaptiveCriteriaList.begin(); runner != AdaptiveCriteriaList.end(); runner++) {
     2831                                Walker = FindAtom((*runner).first);
     2832                                if (Walker != NULL) {
     2833                                        //if ((*runner).second.second >= Walker->AdaptiveOrder) { // only insert if this is an "active" root site for the current order
     2834                                        if (!Walker->MaxOrder) {
     2835                                                *out << Verbose(2) << "(" << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "])" << endl;
     2836                                                FinalRootCandidates.insert( make_pair( (*runner).second.first, pair<int,int>((*runner).first, (*runner).second.second) ) );
     2837                                        } else {
     2838                                                *out << Verbose(2) << "Excluding (" << *Walker << ", " << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "]), as it has reached its maximum order." << endl;
     2839                                        }
     2840                                } else {
     2841                                        cerr << "Atom No. " << (*runner).second.first << " was not found in this molecule." << endl;
     2842                                }
     2843                        }
     2844                        // pick the ones still below threshold and mark as to be adaptively updated
     2845                        for(map<double, pair<int,int> >::iterator runner = FinalRootCandidates.upper_bound(pow(10.,Order)); runner != FinalRootCandidates.end(); runner++) {
     2846                                No = (*runner).second.first;
     2847                                Walker = FindAtom(No);
     2848                                //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) {
     2849                                        *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl;
     2850                                        AtomMask[No] = true;
     2851                                        status = true;
     2852                                //} else
     2853                                        //*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;
     2854                        }
     2855                        // close and done
     2856                        InputFile.close();
     2857                        InputFile.clear();
     2858                } else {
     2859                        cerr << "Unable to parse " << buffer << " file, incrementing all." << endl;
     2860                        while (Walker->next != end) {
     2861                                Walker = Walker->next;
     2862                #ifdef ADDHYDROGEN
     2863                                if (Walker->type->Z != 1) // skip hydrogen
     2864                #endif
     2865                                {
     2866                                        AtomMask[Walker->nr] = true;    // include all (non-hydrogen) atoms
     2867                                        status = true;
     2868                                }
     2869                        }
     2870                }
     2871                Free((void **)&buffer, "molecule::CheckOrderAtSite: *buffer");
     2872                // pick a given number of highest values and set AtomMask
     2873        } else { // global increase of Bond Order
     2874                while (Walker->next != end) {
     2875                        Walker = Walker->next;
     2876        #ifdef ADDHYDROGEN
     2877                        if (Walker->type->Z != 1) // skip hydrogen
     2878        #endif
     2879                        {
     2880                                AtomMask[Walker->nr] = true;    // include all (non-hydrogen) atoms
     2881                                if ((Order != 0) && (Walker->AdaptiveOrder < Order)) // && (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]))
     2882                                        status = true;
     2883                        }
     2884                }
     2885                if ((Order == 0) && (AtomMask[AtomCount] == false))     // single stepping, just check
     2886                        status = true;
     2887
     2888                if (!status) {
     2889                        if (Order == 0)
     2890                                *out << Verbose(1) << "Single stepping done." << endl;
     2891                        else
     2892                                *out << Verbose(1) << "Order at every site is already equal or above desired order " << Order << "." << endl;
     2893                }
     2894        }
     2895
     2896        // print atom mask for debugging
     2897        *out << "                                                       ";
     2898        for(int i=0;i<AtomCount;i++)
     2899                *out << (i % 10);
     2900        *out << endl << "Atom mask is: ";
     2901        for(int i=0;i<AtomCount;i++)
     2902                *out << (AtomMask[i] ? "t" : "f");
     2903        *out << endl;
     2904
     2905        return status;
    29072906};
    29082907
     
    29142913bool molecule::CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex)
    29152914{
    2916   element *runner = elemente->start;
    2917   int AtomNo = 0;
    2918   atom *Walker = NULL;
    2919 
    2920   if (SortIndex != NULL) {
    2921     *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl;
    2922     return false;
    2923   }
    2924   SortIndex = (int *) Malloc(sizeof(int)*AtomCount, "molecule::FragmentMolecule: *SortIndex");
    2925   for(int i=AtomCount;i--;)
    2926     SortIndex[i] = -1;
    2927   while (runner->next != elemente->end) { // go through every element
    2928     runner = runner->next;
    2929     if (ElementsInMolecule[runner->Z]) { // if this element got atoms
    2930       Walker = start;
    2931       while (Walker->next != end) { // go through every atom of this element
    2932         Walker = Walker->next;
    2933         if (Walker->type->Z == runner->Z) // if this atom fits to element
    2934           SortIndex[Walker->nr] = AtomNo++;
    2935       }
    2936     }
    2937   }
    2938   return true;
     2915        element *runner = elemente->start;
     2916        int AtomNo = 0;
     2917        atom *Walker = NULL;
     2918
     2919        if (SortIndex != NULL) {
     2920                *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl;
     2921                return false;
     2922        }
     2923        SortIndex = (int *) Malloc(sizeof(int)*AtomCount, "molecule::FragmentMolecule: *SortIndex");
     2924        for(int i=AtomCount;i--;)
     2925                SortIndex[i] = -1;
     2926        while (runner->next != elemente->end) { // go through every element
     2927                runner = runner->next;
     2928                if (ElementsInMolecule[runner->Z]) { // if this element got atoms
     2929                        Walker = start;
     2930                        while (Walker->next != end) { // go through every atom of this element
     2931                                Walker = Walker->next;
     2932                                if (Walker->type->Z == runner->Z) // if this atom fits to element
     2933                                        SortIndex[Walker->nr] = AtomNo++;
     2934                        }
     2935                }
     2936        }
     2937        return true;
    29392938};
    29402939
     
    29452944y contribution", and that's why this consciously not done in the following loop)
    29462945 * -# in a loop over all subgraphs
    2947  *  -# calls FragmentBOSSANOVA with this RootStack and within the subgraph molecule structure
    2948  *  -# creates molecule (fragment)s from the returned keysets (StoreFragmentFromKeySet)
     2946 *      -# calls FragmentBOSSANOVA with this RootStack and within the subgraph molecule structure
     2947 *      -# creates molecule (fragment)s from the returned keysets (StoreFragmentFromKeySet)
    29492948 * -# combines the generated molecule lists from all subgraphs
    29502949 * -# saves to disk: fragment configs, adjacency, orderatsite, keyset files
     
    29602959{
    29612960        MoleculeListClass *BondFragments = NULL;
    2962   int *SortIndex = NULL;
    2963   int *MinimumRingSize = new int[AtomCount];
    2964   int FragmentCounter;
    2965   MoleculeLeafClass *MolecularWalker = NULL;
    2966   MoleculeLeafClass *Subgraphs = NULL;      // list of subgraphs from DFS analysis
    2967   fstream File;
    2968   bool FragmentationToDo = true;
    2969   class StackClass<bond *> *BackEdgeStack = NULL, *LocalBackEdgeStack = NULL;
    2970   bool CheckOrder = false;
    2971   Graph **FragmentList = NULL;
    2972   Graph *ParsedFragmentList = NULL;
    2973   Graph TotalGraph;    // graph with all keysets however local numbers
    2974   int TotalNumberOfKeySets = 0;
    2975   atom **ListOfAtoms = NULL;
    2976   atom ***ListOfLocalAtoms = NULL;
    2977   bool *AtomMask = NULL;
    2978 
    2979   *out << endl;
     2961        int *SortIndex = NULL;
     2962        int *MinimumRingSize = new int[AtomCount];
     2963        int FragmentCounter;
     2964        MoleculeLeafClass *MolecularWalker = NULL;
     2965        MoleculeLeafClass *Subgraphs = NULL;                    // list of subgraphs from DFS analysis
     2966        fstream File;
     2967        bool FragmentationToDo = true;
     2968        class StackClass<bond *> *BackEdgeStack = NULL, *LocalBackEdgeStack = NULL;
     2969        bool CheckOrder = false;
     2970        Graph **FragmentList = NULL;
     2971        Graph *ParsedFragmentList = NULL;
     2972        Graph TotalGraph;                // graph with all keysets however local numbers
     2973        int TotalNumberOfKeySets = 0;
     2974        atom **ListOfAtoms = NULL;
     2975        atom ***ListOfLocalAtoms = NULL;
     2976        bool *AtomMask = NULL;
     2977
     2978        *out << endl;
    29802979#ifdef ADDHYDROGEN
    2981   *out << Verbose(0) << "I will treat hydrogen special and saturate dangling bonds with it." << endl;
     2980        *out << Verbose(0) << "I will treat hydrogen special and saturate dangling bonds with it." << endl;
    29822981#else
    2983   *out << Verbose(0) << "Hydrogen is treated just like the rest of the lot." << endl;
     2982        *out << Verbose(0) << "Hydrogen is treated just like the rest of the lot." << endl;
    29842983#endif
    29852984
    2986   // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++
    2987 
    2988   // ===== 1. Check whether bond structure is same as stored in files ====
    2989 
    2990   // fill the adjacency list
    2991   CreateListOfBondsPerAtom(out);
    2992 
    2993   // create lookup table for Atom::nr
    2994   FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount);
    2995 
    2996   // === compare it with adjacency file ===
    2997   FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms);
    2998   Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms");
    2999 
    3000   // ===== 2. perform a DFS analysis to gather info on cyclic structure and a list of disconnected subgraphs =====
    3001   Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack);
    3002   // fill the bond structure of the individually stored subgraphs
    3003   Subgraphs->next->FillBondStructureFromReference(out, this, (FragmentCounter = 0), ListOfLocalAtoms, false);  // we want to keep the created ListOfLocalAtoms
    3004   // analysis of the cycles (print rings, get minimum cycle length) for each subgraph
    3005   for(int i=AtomCount;i--;)
    3006     MinimumRingSize[i] = AtomCount;
    3007   MolecularWalker = Subgraphs;
    3008   FragmentCounter = 0;
    3009   while (MolecularWalker->next != NULL) {
    3010     MolecularWalker = MolecularWalker->next;
    3011     LocalBackEdgeStack = new StackClass<bond *> (MolecularWalker->Leaf->BondCount);
    3012 //    // check the list of local atoms for debugging
    3013 //    *out << Verbose(0) << "ListOfLocalAtoms for this subgraph is:" << endl;
    3014 //    for (int i=0;i<AtomCount;i++)
    3015 //      if (ListOfLocalAtoms[FragmentCounter][i] == NULL)
    3016 //        *out << "\tNULL";
    3017 //      else
    3018 //        *out << "\t" << ListOfLocalAtoms[FragmentCounter][i]->Name;
    3019     *out << Verbose(0) << "Gathering local back edges for subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;
    3020     MolecularWalker->Leaf->PickLocalBackEdges(out, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack);
    3021     *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;
    3022     MolecularWalker->Leaf->CyclicStructureAnalysis(out, LocalBackEdgeStack, MinimumRingSize);
    3023     *out << Verbose(0) << "Done with Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;
    3024     delete(LocalBackEdgeStack);
    3025   }
    3026 
    3027   // ===== 3. if structure still valid, parse key set file and others =====
    3028   FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList);
    3029 
    3030   // ===== 4. check globally whether there's something to do actually (first adaptivity check)
    3031   FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath);
    3032 
    3033   // =================================== Begin of FRAGMENTATION ===============================
    3034   // ===== 6a. assign each keyset to its respective subgraph =====
    3035   Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true);
    3036 
    3037   // ===== 6b. prepare and go into the adaptive (Order<0), single-step (Order==0) or incremental (Order>0) cycle
    3038   KeyStack *RootStack = new KeyStack[Subgraphs->next->Count()];
    3039   AtomMask = new bool[AtomCount+1];
    3040   AtomMask[AtomCount] = false;
    3041   FragmentationToDo = false;  // if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards
    3042   while ((CheckOrder = CheckOrderAtSite(out, AtomMask, ParsedFragmentList, Order, MinimumRingSize, configuration->configpath))) {
    3043     FragmentationToDo = FragmentationToDo || CheckOrder;
    3044     AtomMask[AtomCount] = true;  // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite()
    3045     // ===== 6b. fill RootStack for each subgraph (second adaptivity check) =====
    3046     Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0));
    3047 
    3048     // ===== 7. fill the bond fragment list =====
    3049     FragmentCounter = 0;
    3050     MolecularWalker = Subgraphs;
    3051     while (MolecularWalker->next != NULL) {
    3052       MolecularWalker = MolecularWalker->next;
    3053       *out << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl;
    3054       //MolecularWalker->Leaf->OutputListOfBonds(out);  // output ListOfBondsPerAtom for debugging
    3055       if (MolecularWalker->Leaf->first->next != MolecularWalker->Leaf->last) {
    3056         // call BOSSANOVA method
    3057         *out << Verbose(0) << endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= " << endl;
    3058         MolecularWalker->Leaf->FragmentBOSSANOVA(out, FragmentList[FragmentCounter], RootStack[FragmentCounter], MinimumRingSize);
    3059       } else {
    3060         cerr << "Subgraph " << MolecularWalker << " has no atoms!" << endl;
    3061       }
    3062       FragmentCounter++;  // next fragment list
    3063     }
    3064   }
    3065   delete[](RootStack);
    3066   delete[](AtomMask);
    3067   delete(ParsedFragmentList);
    3068   delete[](MinimumRingSize);
    3069 
    3070 
    3071   // ==================================== End of FRAGMENTATION ============================================
    3072 
    3073   // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf)
    3074   Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph);
    3075 
    3076   // free subgraph memory again
    3077   FragmentCounter = 0;
    3078   if (Subgraphs != NULL) {
    3079     while (Subgraphs->next != NULL) {
    3080       Subgraphs = Subgraphs->next;
    3081       delete(FragmentList[FragmentCounter++]);
    3082       delete(Subgraphs->previous);
    3083     }
    3084     delete(Subgraphs);
    3085   }
    3086   Free((void **)&FragmentList, "molecule::FragmentMolecule - **FragmentList");
    3087 
    3088   // ===== 8b. gather keyset lists (graphs) from all subgraphs and transform into MoleculeListClass =====
    3089   //if (FragmentationToDo) {    // we should always store the fragments again as coordination might have changed slightly without changing bond structure
    3090     // allocate memory for the pointer array and transmorph graphs into full molecular fragments
    3091     BondFragments = new MoleculeListClass(TotalGraph.size(), AtomCount);
    3092     int k=0;
    3093     for(Graph::iterator runner = TotalGraph.begin(); runner != TotalGraph.end(); runner++) {
    3094       KeySet test = (*runner).first;
    3095       *out << "Fragment No." << (*runner).second.first << " with TEFactor " << (*runner).second.second << "." << endl;
    3096       BondFragments->ListOfMolecules[k] = StoreFragmentFromKeySet(out, test, configuration);
    3097       k++;
    3098     }
    3099     *out << k << "/" << BondFragments->NumberOfMolecules << " fragments generated from the keysets." << endl;
    3100 
    3101     // ===== 9. Save fragments' configuration and keyset files et al to disk ===
    3102     if (BondFragments->NumberOfMolecules != 0) {
    3103       // create the SortIndex from BFS labels to order in the config file
    3104       CreateMappingLabelsToConfigSequence(out, SortIndex);
    3105 
    3106       *out << Verbose(1) << "Writing " << BondFragments->NumberOfMolecules << " possible bond fragmentation configs" << endl;
    3107       if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex))
    3108         *out << Verbose(1) << "All configs written." << endl;
    3109       else
    3110         *out << Verbose(1) << "Some config writing failed." << endl;
    3111 
    3112       // store force index reference file
    3113       BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex);
    3114 
    3115       // store keysets file
    3116       StoreKeySetFile(out, TotalGraph, configuration->configpath);
    3117 
    3118       // store Adjacency file
    3119       StoreAdjacencyToFile(out, configuration->configpath);
    3120 
    3121       // store Hydrogen saturation correction file
    3122       BondFragments->AddHydrogenCorrection(out, configuration->configpath);
    3123 
    3124       // store adaptive orders into file
    3125       StoreOrderAtSiteFile(out, configuration->configpath);
    3126 
    3127       // restore orbital and Stop values
    3128       CalculateOrbitals(*configuration);
    3129 
    3130       // free memory for bond part
    3131       *out << Verbose(1) << "Freeing bond memory" << endl;
    3132       delete(FragmentList); // remove bond molecule from memory
    3133       Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex");
    3134     } else
    3135       *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl;
    3136   //} else
    3137   //  *out << Verbose(1) << "No fragments to store." << endl;
    3138   *out << Verbose(0) << "End of bond fragmentation." << endl;
    3139 
    3140   return ((int)(!FragmentationToDo)+1);    // 1 - continue, 2 - stop (no fragmentation occured)
     2985        // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++
     2986
     2987        // ===== 1. Check whether bond structure is same as stored in files ====
     2988
     2989        // fill the adjacency list
     2990        CreateListOfBondsPerAtom(out);
     2991
     2992        // create lookup table for Atom::nr
     2993        FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount);
     2994
     2995        // === compare it with adjacency file ===
     2996        FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms);
     2997        Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms");
     2998
     2999        // ===== 2. perform a DFS analysis to gather info on cyclic structure and a list of disconnected subgraphs =====
     3000        Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack);
     3001        // fill the bond structure of the individually stored subgraphs
     3002        Subgraphs->next->FillBondStructureFromReference(out, this, (FragmentCounter = 0), ListOfLocalAtoms, false);     // we want to keep the created ListOfLocalAtoms
     3003        // analysis of the cycles (print rings, get minimum cycle length) for each subgraph
     3004        for(int i=AtomCount;i--;)
     3005                MinimumRingSize[i] = AtomCount;
     3006        MolecularWalker = Subgraphs;
     3007        FragmentCounter = 0;
     3008        while (MolecularWalker->next != NULL) {
     3009                MolecularWalker = MolecularWalker->next;
     3010                LocalBackEdgeStack = new StackClass<bond *> (MolecularWalker->Leaf->BondCount);
     3011//              // check the list of local atoms for debugging
     3012//              *out << Verbose(0) << "ListOfLocalAtoms for this subgraph is:" << endl;
     3013//              for (int i=0;i<AtomCount;i++)
     3014//                      if (ListOfLocalAtoms[FragmentCounter][i] == NULL)
     3015//                              *out << "\tNULL";
     3016//                      else
     3017//                              *out << "\t" << ListOfLocalAtoms[FragmentCounter][i]->Name;
     3018                *out << Verbose(0) << "Gathering local back edges for subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;
     3019                MolecularWalker->Leaf->PickLocalBackEdges(out, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack);
     3020                *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;
     3021                MolecularWalker->Leaf->CyclicStructureAnalysis(out, LocalBackEdgeStack, MinimumRingSize);
     3022                *out << Verbose(0) << "Done with Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;
     3023                delete(LocalBackEdgeStack);
     3024        }
     3025
     3026        // ===== 3. if structure still valid, parse key set file and others =====
     3027        FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList);
     3028
     3029        // ===== 4. check globally whether there's something to do actually (first adaptivity check)
     3030        FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath);
     3031
     3032        // =================================== Begin of FRAGMENTATION ===============================
     3033        // ===== 6a. assign each keyset to its respective subgraph =====
     3034        Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true);
     3035
     3036        // ===== 6b. prepare and go into the adaptive (Order<0), single-step (Order==0) or incremental (Order>0) cycle
     3037        KeyStack *RootStack = new KeyStack[Subgraphs->next->Count()];
     3038        AtomMask = new bool[AtomCount+1];
     3039        AtomMask[AtomCount] = false;
     3040        FragmentationToDo = false;      // if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards
     3041        while ((CheckOrder = CheckOrderAtSite(out, AtomMask, ParsedFragmentList, Order, MinimumRingSize, configuration->configpath))) {
     3042                FragmentationToDo = FragmentationToDo || CheckOrder;
     3043                AtomMask[AtomCount] = true;      // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite()
     3044                // ===== 6b. fill RootStack for each subgraph (second adaptivity check) =====
     3045                Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0));
     3046
     3047                // ===== 7. fill the bond fragment list =====
     3048                FragmentCounter = 0;
     3049                MolecularWalker = Subgraphs;
     3050                while (MolecularWalker->next != NULL) {
     3051                        MolecularWalker = MolecularWalker->next;
     3052                        *out << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl;
     3053                        //MolecularWalker->Leaf->OutputListOfBonds(out);        // output ListOfBondsPerAtom for debugging
     3054                        if (MolecularWalker->Leaf->first->next != MolecularWalker->Leaf->last) {
     3055                                // call BOSSANOVA method
     3056                                *out << Verbose(0) << endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= " << endl;
     3057                                MolecularWalker->Leaf->FragmentBOSSANOVA(out, FragmentList[FragmentCounter], RootStack[FragmentCounter], MinimumRingSize);
     3058                        } else {
     3059                                cerr << "Subgraph " << MolecularWalker << " has no atoms!" << endl;
     3060                        }
     3061                        FragmentCounter++;      // next fragment list
     3062                }
     3063        }
     3064        delete[](RootStack);
     3065        delete[](AtomMask);
     3066        delete(ParsedFragmentList);
     3067        delete[](MinimumRingSize);
     3068
     3069
     3070        // ==================================== End of FRAGMENTATION ============================================
     3071
     3072        // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf)
     3073        Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph);
     3074
     3075        // free subgraph memory again
     3076        FragmentCounter = 0;
     3077        if (Subgraphs != NULL) {
     3078                while (Subgraphs->next != NULL) {
     3079                        Subgraphs = Subgraphs->next;
     3080                        delete(FragmentList[FragmentCounter++]);
     3081                        delete(Subgraphs->previous);
     3082                }
     3083                delete(Subgraphs);
     3084        }
     3085        Free((void **)&FragmentList, "molecule::FragmentMolecule - **FragmentList");
     3086
     3087        // ===== 8b. gather keyset lists (graphs) from all subgraphs and transform into MoleculeListClass =====
     3088        //if (FragmentationToDo) {              // we should always store the fragments again as coordination might have changed slightly without changing bond structure
     3089                // allocate memory for the pointer array and transmorph graphs into full molecular fragments
     3090                BondFragments = new MoleculeListClass(TotalGraph.size(), AtomCount);
     3091                int k=0;
     3092                for(Graph::iterator runner = TotalGraph.begin(); runner != TotalGraph.end(); runner++) {
     3093                        KeySet test = (*runner).first;
     3094                        *out << "Fragment No." << (*runner).second.first << " with TEFactor " << (*runner).second.second << "." << endl;
     3095                        BondFragments->ListOfMolecules[k] = StoreFragmentFromKeySet(out, test, configuration);
     3096                        k++;
     3097                }
     3098                *out << k << "/" << BondFragments->NumberOfMolecules << " fragments generated from the keysets." << endl;
     3099
     3100                // ===== 9. Save fragments' configuration and keyset files et al to disk ===
     3101                if (BondFragments->NumberOfMolecules != 0) {
     3102                        // create the SortIndex from BFS labels to order in the config file
     3103                        CreateMappingLabelsToConfigSequence(out, SortIndex);
     3104
     3105                        *out << Verbose(1) << "Writing " << BondFragments->NumberOfMolecules << " possible bond fragmentation configs" << endl;
     3106                        if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex))
     3107                                *out << Verbose(1) << "All configs written." << endl;
     3108                        else
     3109                                *out << Verbose(1) << "Some config writing failed." << endl;
     3110
     3111                        // store force index reference file
     3112                        BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex);
     3113
     3114                        // store keysets file
     3115                        StoreKeySetFile(out, TotalGraph, configuration->configpath);
     3116
     3117                        // store Adjacency file
     3118                        StoreAdjacencyToFile(out, configuration->configpath);
     3119
     3120                        // store Hydrogen saturation correction file
     3121                        BondFragments->AddHydrogenCorrection(out, configuration->configpath);
     3122
     3123                        // store adaptive orders into file
     3124                        StoreOrderAtSiteFile(out, configuration->configpath);
     3125
     3126                        // restore orbital and Stop values
     3127                        CalculateOrbitals(*configuration);
     3128
     3129                        // free memory for bond part
     3130                        *out << Verbose(1) << "Freeing bond memory" << endl;
     3131                        delete(FragmentList); // remove bond molecule from memory
     3132                        Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex");
     3133                } else
     3134                        *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl;
     3135        //} else
     3136        //      *out << Verbose(1) << "No fragments to store." << endl;
     3137        *out << Verbose(0) << "End of bond fragmentation." << endl;
     3138
     3139        return ((int)(!FragmentationToDo)+1);           // 1 - continue, 2 - stop (no fragmentation occured)
    31413140};
    31423141
     
    31513150bool molecule::PickLocalBackEdges(ofstream *out, atom **ListOfLocalAtoms, class StackClass<bond *> *&ReferenceStack, class StackClass<bond *> *&LocalStack)
    31523151{
    3153   bool status = true;
    3154   if (ReferenceStack->IsEmpty()) {
    3155     cerr << "ReferenceStack is empty!" << endl;
    3156     return false;
    3157   }
    3158   bond *Binder = ReferenceStack->PopFirst();
    3159   bond *FirstBond = Binder;  // mark the first bond, so that we don't loop through the stack indefinitely
    3160   atom *Walker = NULL, *OtherAtom = NULL;
    3161   ReferenceStack->Push(Binder);
    3162 
    3163   do {  // go through all bonds and push local ones
    3164     Walker = ListOfLocalAtoms[Binder->leftatom->nr];  // get one atom in the reference molecule
    3165     if (Walker != NULL) // if this Walker exists in the subgraph ...
    3166         for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {    // go through the local list of bonds
    3167         OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
    3168               if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond
    3169               LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]);
     3152        bool status = true;
     3153        if (ReferenceStack->IsEmpty()) {
     3154                cerr << "ReferenceStack is empty!" << endl;
     3155                return false;
     3156        }
     3157        bond *Binder = ReferenceStack->PopFirst();
     3158        bond *FirstBond = Binder;        // mark the first bond, so that we don't loop through the stack indefinitely
     3159        atom *Walker = NULL, *OtherAtom = NULL;
     3160        ReferenceStack->Push(Binder);
     3161
     3162        do {    // go through all bonds and push local ones
     3163                Walker = ListOfLocalAtoms[Binder->leftatom->nr];        // get one atom in the reference molecule
     3164                if (Walker != NULL) // if this Walker exists in the subgraph ...
     3165                        for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {           // go through the local list of bonds
     3166                                OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
     3167                                if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond
     3168                                        LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]);
    31703169                                        *out << Verbose(3) << "Found local edge " << *(ListOfBondsPerAtom[Walker->nr][i]) << "." << endl;
    3171                 break;
    3172             }
    3173         }
    3174     Binder = ReferenceStack->PopFirst();  // loop the stack for next item
     3170                                        break;
     3171                                }
     3172                        }
     3173                Binder = ReferenceStack->PopFirst();    // loop the stack for next item
    31753174                *out << Verbose(3) << "Current candidate edge " << Binder << "." << endl;
    3176     ReferenceStack->Push(Binder);
    3177   } while (FirstBond != Binder);
    3178 
    3179   return status;
     3175                ReferenceStack->Push(Binder);
     3176        } while (FirstBond != Binder);
     3177
     3178        return status;
    31803179};
    31813180
     
    31883187bool molecule::StoreOrderAtSiteFile(ofstream *out, char *path)
    31893188{
    3190   stringstream line;
    3191   ofstream file;
    3192 
    3193   line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE;
    3194   file.open(line.str().c_str());
    3195   *out << Verbose(1) << "Writing OrderAtSite " << ORDERATSITEFILE << " ... " << endl;
    3196   if (file != NULL) {
    3197     atom *Walker = start;
    3198     while (Walker->next != end) {
    3199       Walker = Walker->next;
    3200       file << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << endl;
    3201       *out << Verbose(2) << "Storing: " << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << "." << endl;
    3202     }
    3203     file.close();
    3204     *out << Verbose(1) << "done." << endl;
    3205     return true;
    3206   } else {
    3207     *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;
    3208     return false;
    3209   }
     3189        stringstream line;
     3190        ofstream file;
     3191
     3192        line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE;
     3193        file.open(line.str().c_str());
     3194        *out << Verbose(1) << "Writing OrderAtSite " << ORDERATSITEFILE << " ... " << endl;
     3195        if (file != NULL) {
     3196                atom *Walker = start;
     3197                while (Walker->next != end) {
     3198                        Walker = Walker->next;
     3199                        file << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << endl;
     3200                        *out << Verbose(2) << "Storing: " << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << "." << endl;
     3201                }
     3202                file.close();
     3203                *out << Verbose(1) << "done." << endl;
     3204                return true;
     3205        } else {
     3206                *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;
     3207                return false;
     3208        }
    32103209};
    32113210
     
    32193218bool molecule::ParseOrderAtSiteFromFile(ofstream *out, char *path)
    32203219{
    3221   unsigned char *OrderArray = (unsigned char *) Malloc(sizeof(unsigned char)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *OrderArray");
    3222   bool *MaxArray = (bool *) Malloc(sizeof(bool)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *MaxArray");
    3223   bool status;
    3224   int AtomNr, value;
    3225   stringstream line;
    3226   ifstream file;
    3227 
    3228   *out << Verbose(1) << "Begin of ParseOrderAtSiteFromFile" << endl;
    3229   for(int i=AtomCount;i--;)
    3230     OrderArray[i] = 0;
    3231   line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE;
    3232   file.open(line.str().c_str());
    3233   if (file != NULL) {
    3234     for (int i=AtomCount;i--;) { // initialise with 0
    3235       OrderArray[i] = 0;
    3236       MaxArray[i] = 0;
    3237     }
    3238     while (!file.eof()) { // parse from file
    3239       AtomNr = -1;
    3240       file >> AtomNr;
    3241       if (AtomNr != -1) {  // test whether we really parsed something (this is necessary, otherwise last atom is set twice and to 0 on second time)
    3242         file >> value;
    3243         OrderArray[AtomNr] = value;
    3244         file >> value;
    3245         MaxArray[AtomNr] = value;
    3246         //*out << Verbose(2) << "AtomNr " << AtomNr << " with order " << (int)OrderArray[AtomNr] << " and max order set to " << (int)MaxArray[AtomNr] << "." << endl;
    3247       }
    3248     }
    3249     atom *Walker = start;
    3250     while (Walker->next != end) { // fill into atom classes
    3251       Walker = Walker->next;
    3252       Walker->AdaptiveOrder = OrderArray[Walker->nr];
    3253       Walker->MaxOrder = MaxArray[Walker->nr];
    3254       *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl;
    3255     }
    3256     file.close();
    3257     *out << Verbose(1) << "done." << endl;
    3258     status = true;
    3259   } else {
    3260     *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;
    3261     status = false;
    3262   }
    3263   Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray");
    3264   Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray");
    3265 
    3266   *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl;
    3267   return status;
     3220        unsigned char *OrderArray = (unsigned char *) Malloc(sizeof(unsigned char)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *OrderArray");
     3221        bool *MaxArray = (bool *) Malloc(sizeof(bool)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *MaxArray");
     3222        bool status;
     3223        int AtomNr, value;
     3224        stringstream line;
     3225        ifstream file;
     3226
     3227        *out << Verbose(1) << "Begin of ParseOrderAtSiteFromFile" << endl;
     3228        for(int i=AtomCount;i--;)
     3229                OrderArray[i] = 0;
     3230        line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE;
     3231        file.open(line.str().c_str());
     3232        if (file != NULL) {
     3233                for (int i=AtomCount;i--;) { // initialise with 0
     3234                        OrderArray[i] = 0;
     3235                        MaxArray[i] = 0;
     3236                }
     3237                while (!file.eof()) { // parse from file
     3238                        AtomNr = -1;
     3239                        file >> AtomNr;
     3240                        if (AtomNr != -1) {      // test whether we really parsed something (this is necessary, otherwise last atom is set twice and to 0 on second time)
     3241                                file >> value;
     3242                                OrderArray[AtomNr] = value;
     3243                                file >> value;
     3244                                MaxArray[AtomNr] = value;
     3245                                //*out << Verbose(2) << "AtomNr " << AtomNr << " with order " << (int)OrderArray[AtomNr] << " and max order set to " << (int)MaxArray[AtomNr] << "." << endl;
     3246                        }
     3247                }
     3248                atom *Walker = start;
     3249                while (Walker->next != end) { // fill into atom classes
     3250                        Walker = Walker->next;
     3251                        Walker->AdaptiveOrder = OrderArray[Walker->nr];
     3252                        Walker->MaxOrder = MaxArray[Walker->nr];
     3253                        *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl;
     3254                }
     3255                file.close();
     3256                *out << Verbose(1) << "done." << endl;
     3257                status = true;
     3258        } else {
     3259                *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;
     3260                status = false;
     3261        }
     3262        Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray");
     3263        Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray");
     3264
     3265        *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl;
     3266        return status;
    32683267};
    32693268
     
    32763275void molecule::CreateListOfBondsPerAtom(ofstream *out)
    32773276{
    3278   bond *Binder = NULL;
    3279   atom *Walker = NULL;
    3280   int TotalDegree;
    3281   *out << Verbose(1) << "Begin of Creating ListOfBondsPerAtom: AtomCount = " << AtomCount << "\tBondCount = " << BondCount << "\tNoNonBonds = " << NoNonBonds << "." << endl;
    3282 
    3283   // re-allocate memory
    3284   *out << Verbose(2) << "(Re-)Allocating memory." << endl;
    3285   if (ListOfBondsPerAtom != NULL) {
    3286     for(int i=AtomCount;i--;)
    3287       Free((void **)&ListOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom[i]");
    3288     Free((void **)&ListOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom");
    3289   }
    3290   if (NumberOfBondsPerAtom != NULL)
    3291     Free((void **)&NumberOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: NumberOfBondsPerAtom");
    3292   ListOfBondsPerAtom = (bond ***) Malloc(sizeof(bond **)*AtomCount, "molecule::CreateListOfBondsPerAtom: ***ListOfBondsPerAtom");
    3293   NumberOfBondsPerAtom = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfBondsPerAtom: *NumberOfBondsPerAtom");
    3294 
    3295   // reset bond counts per atom
    3296   for(int i=AtomCount;i--;)
    3297     NumberOfBondsPerAtom[i] = 0;
    3298   // count bonds per atom
    3299   Binder = first;
    3300   while (Binder->next != last) {
    3301     Binder = Binder->next;
    3302     NumberOfBondsPerAtom[Binder->leftatom->nr]++;
    3303     NumberOfBondsPerAtom[Binder->rightatom->nr]++;
    3304   }
    3305   for(int i=AtomCount;i--;) {
    3306     // allocate list of bonds per atom
    3307     ListOfBondsPerAtom[i] = (bond **) Malloc(sizeof(bond *)*NumberOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: **ListOfBondsPerAtom[]");
    3308     // clear the list again, now each NumberOfBondsPerAtom marks current free field
    3309     NumberOfBondsPerAtom[i] = 0;
    3310   }
    3311   // fill the list
    3312   Binder = first;
    3313   while (Binder->next != last) {
    3314     Binder = Binder->next;
    3315     ListOfBondsPerAtom[Binder->leftatom->nr][NumberOfBondsPerAtom[Binder->leftatom->nr]++] = Binder;
    3316     ListOfBondsPerAtom[Binder->rightatom->nr][NumberOfBondsPerAtom[Binder->rightatom->nr]++] = Binder;
    3317   }
    3318 
    3319   // output list for debugging
    3320   *out << Verbose(3) << "ListOfBondsPerAtom for each atom:" << endl;
    3321   Walker = start;
    3322   while (Walker->next != end) {
    3323     Walker = Walker->next;
    3324     *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: ";
    3325     TotalDegree = 0;
    3326     for (int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) {
    3327       *out << *ListOfBondsPerAtom[Walker->nr][j] << "\t";
    3328       TotalDegree += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;
    3329     }
    3330     *out << " -- TotalDegree: " << TotalDegree << endl;
    3331   }
    3332   *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl;
     3277        bond *Binder = NULL;
     3278        atom *Walker = NULL;
     3279        int TotalDegree;
     3280        *out << Verbose(1) << "Begin of Creating ListOfBondsPerAtom: AtomCount = " << AtomCount << "\tBondCount = " << BondCount << "\tNoNonBonds = " << NoNonBonds << "." << endl;
     3281
     3282        // re-allocate memory
     3283        *out << Verbose(2) << "(Re-)Allocating memory." << endl;
     3284        if (ListOfBondsPerAtom != NULL) {
     3285                for(int i=AtomCount;i--;)
     3286                        Free((void **)&ListOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom[i]");
     3287                Free((void **)&ListOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom");
     3288        }
     3289        if (NumberOfBondsPerAtom != NULL)
     3290                Free((void **)&NumberOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: NumberOfBondsPerAtom");
     3291        ListOfBondsPerAtom = (bond ***) Malloc(sizeof(bond **)*AtomCount, "molecule::CreateListOfBondsPerAtom: ***ListOfBondsPerAtom");
     3292        NumberOfBondsPerAtom = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfBondsPerAtom: *NumberOfBondsPerAtom");
     3293
     3294        // reset bond counts per atom
     3295        for(int i=AtomCount;i--;)
     3296                NumberOfBondsPerAtom[i] = 0;
     3297        // count bonds per atom
     3298        Binder = first;
     3299        while (Binder->next != last) {
     3300                Binder = Binder->next;
     3301                NumberOfBondsPerAtom[Binder->leftatom->nr]++;
     3302                NumberOfBondsPerAtom[Binder->rightatom->nr]++;
     3303        }
     3304        for(int i=AtomCount;i--;) {
     3305                // allocate list of bonds per atom
     3306                ListOfBondsPerAtom[i] = (bond **) Malloc(sizeof(bond *)*NumberOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: **ListOfBondsPerAtom[]");
     3307                // clear the list again, now each NumberOfBondsPerAtom marks current free field
     3308                NumberOfBondsPerAtom[i] = 0;
     3309        }
     3310        // fill the list
     3311        Binder = first;
     3312        while (Binder->next != last) {
     3313                Binder = Binder->next;
     3314                ListOfBondsPerAtom[Binder->leftatom->nr][NumberOfBondsPerAtom[Binder->leftatom->nr]++] = Binder;
     3315                ListOfBondsPerAtom[Binder->rightatom->nr][NumberOfBondsPerAtom[Binder->rightatom->nr]++] = Binder;
     3316        }
     3317
     3318        // output list for debugging
     3319        *out << Verbose(3) << "ListOfBondsPerAtom for each atom:" << endl;
     3320        Walker = start;
     3321        while (Walker->next != end) {
     3322                Walker = Walker->next;
     3323                *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: ";
     3324                TotalDegree = 0;
     3325                for (int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) {
     3326                        *out << *ListOfBondsPerAtom[Walker->nr][j] << "\t";
     3327                        TotalDegree += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;
     3328                }
     3329                *out << " -- TotalDegree: " << TotalDegree << endl;
     3330        }
     3331        *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl;
    33333332};
    33343333
     
    33473346void molecule::BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem)
    33483347{
    3349   atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::BreadthFirstSearchAdd: **PredecessorList");
    3350   int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::BreadthFirstSearchAdd: *ShortestPathList");
    3351   enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::BreadthFirstSearchAdd: *ColorList");
    3352   class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);
    3353   atom *Walker = NULL, *OtherAtom = NULL;
    3354   bond *Binder = NULL;
    3355 
    3356   // add Root if not done yet
    3357   AtomStack->ClearStack();
    3358   if (AddedAtomList[Root->nr] == NULL)  // add Root if not yet present
    3359     AddedAtomList[Root->nr] = Mol->AddCopyAtom(Root);
    3360   AtomStack->Push(Root);
    3361 
    3362   // initialise each vertex as white with no predecessor, empty queue, color Root lightgray
    3363   for (int i=AtomCount;i--;) {
    3364     PredecessorList[i] = NULL;
    3365     ShortestPathList[i] = -1;
    3366     if (AddedAtomList[i] != NULL) // mark already present atoms (i.e. Root and maybe others) as visited
    3367       ColorList[i] = lightgray;
    3368     else
    3369       ColorList[i] = white;
    3370   }
    3371   ShortestPathList[Root->nr] = 0;
    3372 
    3373   // and go on ... Queue always contains all lightgray vertices
    3374   while (!AtomStack->IsEmpty()) {
    3375     // we have to pop the oldest atom from stack. This keeps the atoms on the stack always of the same ShortestPath distance.
    3376     // 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
    3377     // append length of 3 (their neighbours). Thus on stack we have always atoms of a certain length n at bottom of stack and
    3378     // followed by n+1 till top of stack.
    3379     Walker = AtomStack->PopFirst(); // pop oldest added
    3380     *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl;
    3381     for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
    3382       Binder = ListOfBondsPerAtom[Walker->nr][i];
    3383       if (Binder != NULL) { // don't look at bond equal NULL
    3384         OtherAtom = Binder->GetOtherAtom(Walker);
    3385         *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
    3386         if (ColorList[OtherAtom->nr] == white) {
    3387           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)
    3388             ColorList[OtherAtom->nr] = lightgray;
    3389           PredecessorList[OtherAtom->nr] = Walker;  // Walker is the predecessor
    3390           ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
    3391           *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;
    3392           if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance
    3393             *out << Verbose(3);
    3394             if (AddedAtomList[OtherAtom->nr] == NULL) { // add if it's not been so far
    3395               AddedAtomList[OtherAtom->nr] = Mol->AddCopyAtom(OtherAtom);
    3396               *out << "Added OtherAtom " << OtherAtom->Name;
    3397               AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
    3398               AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
    3399               AddedBondList[Binder->nr]->Type = Binder->Type;
    3400               *out << " and bond " << *(AddedBondList[Binder->nr]) << ", ";
    3401             } 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)
    3402               *out << "Not adding OtherAtom " << OtherAtom->Name;
    3403               if (AddedBondList[Binder->nr] == NULL) {
    3404                 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
    3405                 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
    3406                 AddedBondList[Binder->nr]->Type = Binder->Type;
    3407                 *out << ", added Bond " << *(AddedBondList[Binder->nr]);
    3408               } else
    3409                 *out << ", not added Bond ";
    3410             }
    3411             *out << ", putting OtherAtom into queue." << endl;
    3412             AtomStack->Push(OtherAtom);
    3413           } else { // out of bond order, then replace
    3414             if ((AddedAtomList[OtherAtom->nr] == NULL) && (Binder->Cyclic))
    3415               ColorList[OtherAtom->nr] = white; // unmark if it has not been queued/added, to make it available via its other bonds (cyclic)
    3416             if (Binder == Bond)
    3417               *out << Verbose(3) << "Not Queueing, is the Root bond";
    3418             else if (ShortestPathList[OtherAtom->nr] >= BondOrder)
    3419               *out << Verbose(3) << "Not Queueing, is out of Bond Count of " << BondOrder;
    3420             if (!Binder->Cyclic)
    3421               *out << ", is not part of a cyclic bond, saturating bond with Hydrogen." << endl;
    3422             if (AddedBondList[Binder->nr] == NULL) {
    3423               if ((AddedAtomList[OtherAtom->nr] != NULL)) { // .. whether we add or saturate
    3424                 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
    3425                 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
    3426                 AddedBondList[Binder->nr]->Type = Binder->Type;
    3427               } else {
     3348        atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::BreadthFirstSearchAdd: **PredecessorList");
     3349        int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::BreadthFirstSearchAdd: *ShortestPathList");
     3350        enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::BreadthFirstSearchAdd: *ColorList");
     3351        class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);
     3352        atom *Walker = NULL, *OtherAtom = NULL;
     3353        bond *Binder = NULL;
     3354
     3355        // add Root if not done yet
     3356        AtomStack->ClearStack();
     3357        if (AddedAtomList[Root->nr] == NULL)    // add Root if not yet present
     3358                AddedAtomList[Root->nr] = Mol->AddCopyAtom(Root);
     3359        AtomStack->Push(Root);
     3360
     3361        // initialise each vertex as white with no predecessor, empty queue, color Root lightgray
     3362        for (int i=AtomCount;i--;) {
     3363                PredecessorList[i] = NULL;
     3364                ShortestPathList[i] = -1;
     3365                if (AddedAtomList[i] != NULL) // mark already present atoms (i.e. Root and maybe others) as visited
     3366                        ColorList[i] = lightgray;
     3367                else
     3368                        ColorList[i] = white;
     3369        }
     3370        ShortestPathList[Root->nr] = 0;
     3371
     3372        // and go on ... Queue always contains all lightgray vertices
     3373        while (!AtomStack->IsEmpty()) {
     3374                // we have to pop the oldest atom from stack. This keeps the atoms on the stack always of the same ShortestPath distance.
     3375                // 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
     3376                // append length of 3 (their neighbours). Thus on stack we have always atoms of a certain length n at bottom of stack and
     3377                // followed by n+1 till top of stack.
     3378                Walker = AtomStack->PopFirst(); // pop oldest added
     3379                *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl;
     3380                for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
     3381                        Binder = ListOfBondsPerAtom[Walker->nr][i];
     3382                        if (Binder != NULL) { // don't look at bond equal NULL
     3383                                OtherAtom = Binder->GetOtherAtom(Walker);
     3384                                *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
     3385                                if (ColorList[OtherAtom->nr] == white) {
     3386                                        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)
     3387                                                ColorList[OtherAtom->nr] = lightgray;
     3388                                        PredecessorList[OtherAtom->nr] = Walker;        // Walker is the predecessor
     3389                                        ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
     3390                                        *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;
     3391                                        if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance
     3392                                                *out << Verbose(3);
     3393                                                if (AddedAtomList[OtherAtom->nr] == NULL) { // add if it's not been so far
     3394                                                        AddedAtomList[OtherAtom->nr] = Mol->AddCopyAtom(OtherAtom);
     3395                                                        *out << "Added OtherAtom " << OtherAtom->Name;
     3396                                                        AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
     3397                                                        AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
     3398                                                        AddedBondList[Binder->nr]->Type = Binder->Type;
     3399                                                        *out << " and bond " << *(AddedBondList[Binder->nr]) << ", ";
     3400                                                } 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)
     3401                                                        *out << "Not adding OtherAtom " << OtherAtom->Name;
     3402                                                        if (AddedBondList[Binder->nr] == NULL) {
     3403                                                                AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
     3404                                                                AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
     3405                                                                AddedBondList[Binder->nr]->Type = Binder->Type;
     3406                                                                *out << ", added Bond " << *(AddedBondList[Binder->nr]);
     3407                                                        } else
     3408                                                                *out << ", not added Bond ";
     3409                                                }
     3410                                                *out << ", putting OtherAtom into queue." << endl;
     3411                                                AtomStack->Push(OtherAtom);
     3412                                        } else { // out of bond order, then replace
     3413                                                if ((AddedAtomList[OtherAtom->nr] == NULL) && (Binder->Cyclic))
     3414                                                        ColorList[OtherAtom->nr] = white; // unmark if it has not been queued/added, to make it available via its other bonds (cyclic)
     3415                                                if (Binder == Bond)
     3416                                                        *out << Verbose(3) << "Not Queueing, is the Root bond";
     3417                                                else if (ShortestPathList[OtherAtom->nr] >= BondOrder)
     3418                                                        *out << Verbose(3) << "Not Queueing, is out of Bond Count of " << BondOrder;
     3419                                                if (!Binder->Cyclic)
     3420                                                        *out << ", is not part of a cyclic bond, saturating bond with Hydrogen." << endl;
     3421                                                if (AddedBondList[Binder->nr] == NULL) {
     3422                                                        if ((AddedAtomList[OtherAtom->nr] != NULL)) { // .. whether we add or saturate
     3423                                                                AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
     3424                                                                AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
     3425                                                                AddedBondList[Binder->nr]->Type = Binder->Type;
     3426                                                        } else {
    34283427#ifdef ADDHYDROGEN
    3429                 if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))
    3430                   exit(1);
     3428                                                                if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))
     3429                                                                        exit(1);
    34313430#endif
    3432               }
    3433             }
    3434           }
    3435         } else {
    3436           *out << Verbose(3) << "Not Adding, has already been visited." << endl;
    3437           // This has to be a cyclic bond, check whether it's present ...
    3438           if (AddedBondList[Binder->nr] == NULL) {
    3439             if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) {
    3440               AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
    3441               AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
    3442               AddedBondList[Binder->nr]->Type = Binder->Type;
    3443             } else { // if it's root bond it has to broken (otherwise we would not create the fragments)
     3431                                                        }
     3432                                                }
     3433                                        }
     3434                                } else {
     3435                                        *out << Verbose(3) << "Not Adding, has already been visited." << endl;
     3436                                        // This has to be a cyclic bond, check whether it's present ...
     3437                                        if (AddedBondList[Binder->nr] == NULL) {
     3438                                                if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) {
     3439                                                        AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
     3440                                                        AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
     3441                                                        AddedBondList[Binder->nr]->Type = Binder->Type;
     3442                                                } else { // if it's root bond it has to broken (otherwise we would not create the fragments)
    34443443#ifdef ADDHYDROGEN
    3445               if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))
    3446                 exit(1);
     3444                                                        if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))
     3445                                                                exit(1);
    34473446#endif
    3448             }
    3449           }
    3450         }
    3451       }
    3452     }
    3453     ColorList[Walker->nr] = black;
    3454     *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
    3455   }
    3456   Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList");
    3457   Free((void **)&ShortestPathList, "molecule::BreadthFirstSearchAdd: **ShortestPathList");
    3458   Free((void **)&ColorList, "molecule::BreadthFirstSearchAdd: **ColorList");
    3459   delete(AtomStack);
     3447                                                }
     3448                                        }
     3449                                }
     3450                        }
     3451                }
     3452                ColorList[Walker->nr] = black;
     3453                *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
     3454        }
     3455        Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList");
     3456        Free((void **)&ShortestPathList, "molecule::BreadthFirstSearchAdd: **ShortestPathList");
     3457        Free((void **)&ColorList, "molecule::BreadthFirstSearchAdd: **ColorList");
     3458        delete(AtomStack);
    34603459};
    34613460
     
    34713470bool molecule::BuildInducedSubgraph(ofstream *out, const molecule *Father)
    34723471{
    3473   atom *Walker = NULL, *OtherAtom = NULL;
    3474   bool status = true;
    3475   atom **ParentList = (atom **) Malloc(sizeof(atom *)*Father->AtomCount, "molecule::BuildInducedSubgraph: **ParentList");
    3476 
    3477   *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl;
    3478 
    3479   // reset parent list
    3480   *out << Verbose(3) << "Resetting ParentList." << endl;
    3481   for (int i=Father->AtomCount;i--;)
    3482     ParentList[i] = NULL;
    3483 
    3484   // fill parent list with sons
    3485   *out << Verbose(3) << "Filling Parent List." << endl;
    3486   Walker = start;
    3487   while (Walker->next != end) {
    3488     Walker = Walker->next;
    3489     ParentList[Walker->father->nr] = Walker;
    3490     // Outputting List for debugging
    3491     *out << Verbose(4) << "Son["<< Walker->father->nr <<"] of " << Walker->father <<  " is " << ParentList[Walker->father->nr] << "." << endl;
    3492   }
    3493 
    3494   // check each entry of parent list and if ok (one-to-and-onto matching) create bonds
    3495   *out << Verbose(3) << "Creating bonds." << endl;
    3496   Walker = Father->start;
    3497   while (Walker->next != Father->end) {
    3498     Walker = Walker->next;
    3499     if (ParentList[Walker->nr] != NULL) {
    3500       if (ParentList[Walker->nr]->father != Walker) {
    3501         status = false;
    3502       } else {
    3503         for (int i=0;i<Father->NumberOfBondsPerAtom[Walker->nr];i++) {
    3504           OtherAtom = Father->ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
    3505           if (ParentList[OtherAtom->nr] != NULL) { // if otheratom is also a father of an atom on this molecule, create the bond
    3506             *out << Verbose(4) << "Endpoints of Bond " << Father->ListOfBondsPerAtom[Walker->nr][i] << " are both present: " << ParentList[Walker->nr]->Name << " and " << ParentList[OtherAtom->nr]->Name << "." << endl;
    3507             AddBond(ParentList[Walker->nr], ParentList[OtherAtom->nr], Father->ListOfBondsPerAtom[Walker->nr][i]->BondDegree);
    3508           }
    3509         }
    3510       }
    3511     }
    3512   }
    3513 
    3514   Free((void **)&ParentList, "molecule::BuildInducedSubgraph: **ParentList");
    3515   *out << Verbose(2) << "End of BuildInducedSubgraph." << endl;
    3516   return status;
     3472        atom *Walker = NULL, *OtherAtom = NULL;
     3473        bool status = true;
     3474        atom **ParentList = (atom **) Malloc(sizeof(atom *)*Father->AtomCount, "molecule::BuildInducedSubgraph: **ParentList");
     3475
     3476        *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl;
     3477
     3478        // reset parent list
     3479        *out << Verbose(3) << "Resetting ParentList." << endl;
     3480        for (int i=Father->AtomCount;i--;)
     3481                ParentList[i] = NULL;
     3482
     3483        // fill parent list with sons
     3484        *out << Verbose(3) << "Filling Parent List." << endl;
     3485        Walker = start;
     3486        while (Walker->next != end) {
     3487                Walker = Walker->next;
     3488                ParentList[Walker->father->nr] = Walker;
     3489                // Outputting List for debugging
     3490                *out << Verbose(4) << "Son["<< Walker->father->nr <<"] of " << Walker->father <<        " is " << ParentList[Walker->father->nr] << "." << endl;
     3491        }
     3492
     3493        // check each entry of parent list and if ok (one-to-and-onto matching) create bonds
     3494        *out << Verbose(3) << "Creating bonds." << endl;
     3495        Walker = Father->start;
     3496        while (Walker->next != Father->end) {
     3497                Walker = Walker->next;
     3498                if (ParentList[Walker->nr] != NULL) {
     3499                        if (ParentList[Walker->nr]->father != Walker) {
     3500                                status = false;
     3501                        } else {
     3502                                for (int i=0;i<Father->NumberOfBondsPerAtom[Walker->nr];i++) {
     3503                                        OtherAtom = Father->ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
     3504                                        if (ParentList[OtherAtom->nr] != NULL) { // if otheratom is also a father of an atom on this molecule, create the bond
     3505                                                *out << Verbose(4) << "Endpoints of Bond " << Father->ListOfBondsPerAtom[Walker->nr][i] << " are both present: " << ParentList[Walker->nr]->Name << " and " << ParentList[OtherAtom->nr]->Name << "." << endl;
     3506                                                AddBond(ParentList[Walker->nr], ParentList[OtherAtom->nr], Father->ListOfBondsPerAtom[Walker->nr][i]->BondDegree);
     3507                                        }
     3508                                }
     3509                        }
     3510                }
     3511        }
     3512
     3513        Free((void **)&ParentList, "molecule::BuildInducedSubgraph: **ParentList");
     3514        *out << Verbose(2) << "End of BuildInducedSubgraph." << endl;
     3515        return status;
    35173516};
    35183517
     
    35263525int molecule::LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList)
    35273526{
    3528   atom *Runner = NULL;
    3529   int SP, Removal;
    3530 
    3531   *out << Verbose(2) << "Looking for removal candidate." << endl;
    3532   SP = -1; //0;  // not -1, so that Root is never removed
    3533   Removal = -1;
    3534   for (KeySet::iterator runner = Leaf->begin(); runner != Leaf->end(); runner++) {
    3535     Runner = FindAtom((*runner));
    3536     if (Runner->type->Z != 1) { // skip all those added hydrogens when re-filling snake stack
    3537       if (ShortestPathList[(*runner)] > SP) {  // remove the oldest one with longest shortest path
    3538         SP = ShortestPathList[(*runner)];
    3539         Removal = (*runner);
    3540       }
    3541     }
    3542   }
    3543   return Removal;
     3527        atom *Runner = NULL;
     3528        int SP, Removal;
     3529
     3530        *out << Verbose(2) << "Looking for removal candidate." << endl;
     3531        SP = -1; //0;   // not -1, so that Root is never removed
     3532        Removal = -1;
     3533        for (KeySet::iterator runner = Leaf->begin(); runner != Leaf->end(); runner++) {
     3534                Runner = FindAtom((*runner));
     3535                if (Runner->type->Z != 1) { // skip all those added hydrogens when re-filling snake stack
     3536                        if (ShortestPathList[(*runner)] > SP) { // remove the oldest one with longest shortest path
     3537                                SP = ShortestPathList[(*runner)];
     3538                                Removal = (*runner);
     3539                        }
     3540                }
     3541        }
     3542        return Removal;
    35443543};
    35453544
     
    35543553molecule * molecule::StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem)
    35553554{
    3556   atom *Runner = NULL, *FatherOfRunner = NULL, *OtherFather = NULL;
    3557   atom **SonList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::StoreFragmentFromStack: **SonList");
    3558   molecule *Leaf = new molecule(elemente);
    3559   bool LonelyFlag = false;
    3560   int size;
    3561 
    3562 //  *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl;
    3563 
    3564   Leaf->BondDistance = BondDistance;
    3565   for(int i=NDIM*2;i--;)
    3566     Leaf->cell_size[i] = cell_size[i];
    3567 
    3568   // initialise SonList (indicates when we need to replace a bond with hydrogen instead)
    3569   for(int i=AtomCount;i--;)
    3570     SonList[i] = NULL;
    3571 
    3572   // first create the minimal set of atoms from the KeySet
    3573   size = 0;
    3574   for(KeySet::iterator runner = Leaflet.begin(); runner != Leaflet.end(); runner++) {
    3575     FatherOfRunner = FindAtom((*runner));  // find the id
    3576     SonList[FatherOfRunner->nr] = Leaf->AddCopyAtom(FatherOfRunner);
    3577     size++;
    3578   }
    3579 
    3580   // create the bonds between all: Make it an induced subgraph and add hydrogen
    3581 //  *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl;
    3582   Runner = Leaf->start;
    3583   while (Runner->next != Leaf->end) {
    3584     Runner = Runner->next;
    3585     LonelyFlag = true;
    3586     FatherOfRunner = Runner->father;
    3587     if (SonList[FatherOfRunner->nr] != NULL)  {  // check if this, our father, is present in list
    3588       // create all bonds
    3589       for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father
    3590         OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner);
    3591 //        *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather;
    3592         if (SonList[OtherFather->nr] != NULL) {
    3593 //          *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl;
    3594           if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba)
    3595 //            *out << Verbose(3) << "Adding Bond: ";
    3596 //            *out <<
    3597             Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree);
    3598 //            *out << "." << endl;
    3599             //NumBonds[Runner->nr]++;
    3600           } else {
    3601 //            *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl;
    3602           }
    3603           LonelyFlag = false;
    3604         } else {
    3605 //          *out << ", who has no son in this fragment molecule." << endl;
     3555        atom *Runner = NULL, *FatherOfRunner = NULL, *OtherFather = NULL;
     3556        atom **SonList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::StoreFragmentFromStack: **SonList");
     3557        molecule *Leaf = new molecule(elemente);
     3558        bool LonelyFlag = false;
     3559        int size;
     3560
     3561//      *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl;
     3562
     3563        Leaf->BondDistance = BondDistance;
     3564        for(int i=NDIM*2;i--;)
     3565                Leaf->cell_size[i] = cell_size[i];
     3566
     3567        // initialise SonList (indicates when we need to replace a bond with hydrogen instead)
     3568        for(int i=AtomCount;i--;)
     3569                SonList[i] = NULL;
     3570
     3571        // first create the minimal set of atoms from the KeySet
     3572        size = 0;
     3573        for(KeySet::iterator runner = Leaflet.begin(); runner != Leaflet.end(); runner++) {
     3574                FatherOfRunner = FindAtom((*runner));   // find the id
     3575                SonList[FatherOfRunner->nr] = Leaf->AddCopyAtom(FatherOfRunner);
     3576                size++;
     3577        }
     3578
     3579        // create the bonds between all: Make it an induced subgraph and add hydrogen
     3580//      *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl;
     3581        Runner = Leaf->start;
     3582        while (Runner->next != Leaf->end) {
     3583                Runner = Runner->next;
     3584                LonelyFlag = true;
     3585                FatherOfRunner = Runner->father;
     3586                if (SonList[FatherOfRunner->nr] != NULL)        {       // check if this, our father, is present in list
     3587                        // create all bonds
     3588                        for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father
     3589                                OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner);
     3590//                              *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather;
     3591                                if (SonList[OtherFather->nr] != NULL) {
     3592//                                      *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl;
     3593                                        if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba)
     3594//                                              *out << Verbose(3) << "Adding Bond: ";
     3595//                                              *out <<
     3596                                                Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree);
     3597//                                              *out << "." << endl;
     3598                                                //NumBonds[Runner->nr]++;
     3599                                        } else {
     3600//                                              *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl;
     3601                                        }
     3602                                        LonelyFlag = false;
     3603                                } else {
     3604//                                      *out << ", who has no son in this fragment molecule." << endl;
    36063605#ifdef ADDHYDROGEN
    3607           //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl;
    3608           if(!Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem))
    3609             exit(1);
     3606                                        //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl;
     3607                                        if(!Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem))
     3608                                                exit(1);
    36103609#endif
    3611           //NumBonds[Runner->nr] += ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree;
    3612         }
    3613       }
    3614     } else {
    3615       *out << Verbose(0) << "ERROR: Son " << Runner->Name << " has father " << FatherOfRunner->Name << " but its entry in SonList is " << SonList[FatherOfRunner->nr] << "!" << endl;
    3616     }
    3617     if ((LonelyFlag) && (size > 1)) {
    3618       *out << Verbose(0) << *Runner << "has got bonds only to hydrogens!" << endl;
    3619     }
     3610                                        //NumBonds[Runner->nr] += ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree;
     3611                                }
     3612                        }
     3613                } else {
     3614                        *out << Verbose(0) << "ERROR: Son " << Runner->Name << " has father " << FatherOfRunner->Name << " but its entry in SonList is " << SonList[FatherOfRunner->nr] << "!" << endl;
     3615                }
     3616                if ((LonelyFlag) && (size > 1)) {
     3617                        *out << Verbose(0) << *Runner << "has got bonds only to hydrogens!" << endl;
     3618                }
    36203619#ifdef ADDHYDROGEN
    3621     while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen
    3622       Runner = Runner->next;
     3620                while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen
     3621                        Runner = Runner->next;
    36233622#endif
    3624   }
    3625   Leaf->CreateListOfBondsPerAtom(out);
    3626   //Leaflet->Leaf->ScanForPeriodicCorrection(out);
    3627   Free((void **)&SonList, "molecule::StoreFragmentFromStack: **SonList");
    3628 //  *out << Verbose(1) << "End of StoreFragmentFromKeyset." << endl;
    3629   return Leaf;
     3623        }
     3624        Leaf->CreateListOfBondsPerAtom(out);
     3625        //Leaflet->Leaf->ScanForPeriodicCorrection(out);
     3626        Free((void **)&SonList, "molecule::StoreFragmentFromStack: **SonList");
     3627//      *out << Verbose(1) << "End of StoreFragmentFromKeyset." << endl;
     3628        return Leaf;
    36303629};
    36313630
     
    36463645MoleculeListClass * molecule::CreateListOfUniqueFragmentsOfOrder(ofstream *out, int Order, config *configuration)
    36473646{
    3648   atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: **PredecessorList");
    3649   int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *ShortestPathList");
    3650   int *Labels = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *Labels");
    3651   enum Shading *ColorVertexList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *ColorList");
    3652   enum Shading *ColorEdgeList = (enum Shading *) Malloc(sizeof(enum Shading)*BondCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *ColorBondList");
    3653   StackClass<atom *> *RootStack = new StackClass<atom *>(AtomCount);
    3654   StackClass<atom *> *TouchedStack = new StackClass<atom *>((int)pow(4,Order)+2); // number of atoms reached from one with maximal 4 bonds plus Root itself
    3655   StackClass<atom *> *SnakeStack = new StackClass<atom *>(Order+1); // equal to Order is not possible, as then the StackClass<atom *> cannot discern between full and empty stack!
    3656   MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL;
    3657   MoleculeListClass *FragmentList = NULL;
    3658   atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL, *Removal = NULL;
    3659   bond *Binder = NULL;
    3660   int RunningIndex = 0, FragmentCounter = 0;
    3661 
    3662   *out << Verbose(1) << "Begin of CreateListOfUniqueFragmentsOfOrder." << endl;
    3663 
    3664   // reset parent list
    3665   *out << Verbose(3) << "Resetting labels, parent, predecessor, color and shortest path lists." << endl;
    3666   for (int i=0;i<AtomCount;i++) { // reset all atom labels
    3667     // initialise each vertex as white with no predecessor, empty queue, color lightgray, not labelled, no sons
     3647        atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: **PredecessorList");
     3648        int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *ShortestPathList");
     3649        int *Labels = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *Labels");
     3650        enum Shading *ColorVertexList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *ColorList");
     3651        enum Shading *ColorEdgeList = (enum Shading *) Malloc(sizeof(enum Shading)*BondCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *ColorBondList");
     3652        StackClass<atom *> *RootStack = new StackClass<atom *>(AtomCount);
     3653        StackClass<atom *> *TouchedStack = new StackClass<atom *>((int)pow(4,Order)+2); // number of atoms reached from one with maximal 4 bonds plus Root itself
     3654        StackClass<atom *> *SnakeStack = new StackClass<atom *>(Order+1); // equal to Order is not possible, as then the StackClass<atom *> cannot discern between full and empty stack!
     3655        MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL;
     3656        MoleculeListClass *FragmentList = NULL;
     3657        atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL, *Removal = NULL;
     3658        bond *Binder = NULL;
     3659        int RunningIndex = 0, FragmentCounter = 0;
     3660
     3661        *out << Verbose(1) << "Begin of CreateListOfUniqueFragmentsOfOrder." << endl;
     3662
     3663        // reset parent list
     3664        *out << Verbose(3) << "Resetting labels, parent, predecessor, color and shortest path lists." << endl;
     3665        for (int i=0;i<AtomCount;i++) { // reset all atom labels
     3666                // initialise each vertex as white with no predecessor, empty queue, color lightgray, not labelled, no sons
    36683667                Labels[i] = -1;
    3669     SonList[i] = NULL;
    3670     PredecessorList[i] = NULL;
    3671     ColorVertexList[i] = white;
    3672     ShortestPathList[i] = -1;
    3673   }
    3674   for (int i=0;i<BondCount;i++)
    3675     ColorEdgeList[i] = white;
     3668                SonList[i] = NULL;
     3669                PredecessorList[i] = NULL;
     3670                ColorVertexList[i] = white;
     3671                ShortestPathList[i] = -1;
     3672        }
     3673        for (int i=0;i<BondCount;i++)
     3674                ColorEdgeList[i] = white;
    36763675        RootStack->ClearStack();        // clearstack and push first atom if exists
    3677   TouchedStack->ClearStack();
    3678   Walker = start->next;
    3679   while ((Walker != end)
     3676        TouchedStack->ClearStack();
     3677        Walker = start->next;
     3678        while ((Walker != end)
    36803679#ifdef ADDHYDROGEN
    3681   && (Walker->type->Z == 1)
     3680        && (Walker->type->Z == 1)
    36823681#endif
    3683                         ) { // search for first non-hydrogen atom
    3684     *out << Verbose(4) << "Current Root candidate is " << Walker->Name << "." << endl;
    3685     Walker = Walker->next;
    3686   }
    3687   if (Walker != end)
    3688     RootStack->Push(Walker);
    3689   else
    3690     *out << Verbose(0) << "ERROR: Could not find an appropriate Root atom!" << endl;
    3691   *out << Verbose(3) << "Root " << Walker->Name << " is on AtomStack, beginning loop through all vertices ..." << endl;
    3692 
    3693   ///// OUTER LOOP ////////////
    3694   while (!RootStack->IsEmpty()) {
    3695         // get new root vertex from atom stack
    3696         Root = RootStack->PopFirst();
    3697     ShortestPathList[Root->nr] = 0;
    3698     if (Labels[Root->nr] == -1)
    3699       Labels[Root->nr] = RunningIndex++; // prevent it from getting again on AtomStack
    3700     PredecessorList[Root->nr] = Root;
    3701     TouchedStack->Push(Root);
    3702     *out << Verbose(0) << "Root for this loop is: " << Root->Name << ".\n";
     3682                                                                                                ) { // search for first non-hydrogen atom
     3683                *out << Verbose(4) << "Current Root candidate is " << Walker->Name << "." << endl;
     3684                Walker = Walker->next;
     3685        }
     3686        if (Walker != end)
     3687                RootStack->Push(Walker);
     3688        else
     3689                *out << Verbose(0) << "ERROR: Could not find an appropriate Root atom!" << endl;
     3690        *out << Verbose(3) << "Root " << Walker->Name << " is on AtomStack, beginning loop through all vertices ..." << endl;
     3691
     3692        ///// OUTER LOOP ////////////
     3693        while (!RootStack->IsEmpty()) {
     3694                // get new root vertex from atom stack
     3695                Root = RootStack->PopFirst();
     3696                ShortestPathList[Root->nr] = 0;
     3697                if (Labels[Root->nr] == -1)
     3698                        Labels[Root->nr] = RunningIndex++; // prevent it from getting again on AtomStack
     3699                PredecessorList[Root->nr] = Root;
     3700                TouchedStack->Push(Root);
     3701                *out << Verbose(0) << "Root for this loop is: " << Root->Name << ".\n";
    37033702
    37043703                // clear snake stack
    3705           SnakeStack->ClearStack();
    3706     //SnakeStack->TestImplementation(out, start->next);
    3707 
    3708     ///// INNER LOOP ////////////
    3709     // Problems:
    3710     // - what about cyclic bonds?
    3711     Walker = Root;
    3712         do {
    3713       *out << Verbose(1) << "Current Walker is: " << Walker->Name;
    3714       // initial setting of the new Walker: label, color, shortest path and put on stacks
    3715                 if (Labels[Walker->nr] == -1)   {       // give atom a unique, monotonely increasing number
    3716                         Labels[Walker->nr] = RunningIndex++;
    3717         RootStack->Push(Walker);
    3718       }
    3719       *out << ", has label " << Labels[Walker->nr];
    3720                 if ((ColorVertexList[Walker->nr] == white) || ((Binder != NULL) && (ColorEdgeList[Binder->nr] == white))) {     // color it if newly discovered and push on stacks (and if within reach!)
    3721         if ((Binder != NULL) && (ColorEdgeList[Binder->nr] == white)) {
    3722           // Binder ought to be set still from last neighbour search
    3723           *out << ", coloring bond " << *Binder << " black";
    3724           ColorEdgeList[Binder->nr] = black; // mark this bond as used
    3725         }
    3726         if (ShortestPathList[Walker->nr] == -1) {
    3727           ShortestPathList[Walker->nr] = ShortestPathList[PredecessorList[Walker->nr]->nr]+1;
    3728           TouchedStack->Push(Walker); // mark every atom for lists cleanup later, whose shortest path has been changed
    3729         }
    3730         if ((ShortestPathList[Walker->nr] < Order) && (ColorVertexList[Walker->nr] != darkgray)) {  // if not already on snake stack
    3731           SnakeStack->Push(Walker);
    3732           ColorVertexList[Walker->nr] = darkgray; // mark as dark gray of on snake stack
    3733         }
    3734                 }
    3735       *out << ", SP of " << ShortestPathList[Walker->nr]  << " and its color is " << GetColor(ColorVertexList[Walker->nr]) << "." << endl;
    3736 
    3737       // then check the stack for a newly stumbled upon fragment
    3738                 if (SnakeStack->ItemCount() == Order) { // is stack full?
    3739         // store the fragment if it is one and get a removal candidate
    3740         Removal = StoreFragmentFromStack(out, Root, Walker, Leaflet, SnakeStack, ShortestPathList, SonList, Labels, &FragmentCounter, configuration);
    3741         // remove the candidate if one was found
    3742         if (Removal != NULL) {
    3743           *out << Verbose(2) << "Removing item " << Removal->Name << " with SP of " << ShortestPathList[Removal->nr] << " from snake stack." << endl;
    3744           SnakeStack->RemoveItem(Removal);
    3745           ColorVertexList[Removal->nr] = lightgray; // return back to not on snake stack but explored marking
    3746           if (Walker == Removal) { // if the current atom is to be removed, we also have to take a step back
    3747             Walker = PredecessorList[Removal->nr];
    3748             *out << Verbose(2) << "Stepping back to " << Walker->Name << "." << endl;
    3749           }
    3750         }
    3751                 } else
    3752         Removal = NULL;
    3753 
    3754       // finally, look for a white neighbour as the next Walker
    3755       Binder = NULL;
    3756       if ((Removal == NULL) || (Walker != PredecessorList[Removal->nr])) {  // don't look, if a new walker has been set above
    3757         *out << Verbose(2) << "Snake has currently " << SnakeStack->ItemCount() << " item(s)." << endl;
    3758                         OtherAtom = NULL; // this is actually not needed, every atom has at least one neighbour
    3759         if (ShortestPathList[Walker->nr] < Order) {
    3760                         for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
    3761             Binder = ListOfBondsPerAtom[Walker->nr][i];
    3762             *out << Verbose(2) << "Current bond is " << *Binder << ": ";
    3763                                 OtherAtom = Binder->GetOtherAtom(Walker);
    3764             if ((Labels[OtherAtom->nr] != -1) && (Labels[OtherAtom->nr] < Labels[Root->nr])) { // we don't step up to labels bigger than us
    3765               *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl;
    3766               //ColorVertexList[OtherAtom->nr] = lightgray;    // mark as explored
    3767             } else { // otherwise check its colour and element
    3768                                 if (
     3704                SnakeStack->ClearStack();
     3705                //SnakeStack->TestImplementation(out, start->next);
     3706
     3707                ///// INNER LOOP ////////////
     3708                // Problems:
     3709                // - what about cyclic bonds?
     3710                Walker = Root;
     3711                do {
     3712                        *out << Verbose(1) << "Current Walker is: " << Walker->Name;
     3713                        // initial setting of the new Walker: label, color, shortest path and put on stacks
     3714                        if (Labels[Walker->nr] == -1)   {       // give atom a unique, monotonely increasing number
     3715                                Labels[Walker->nr] = RunningIndex++;
     3716                                RootStack->Push(Walker);
     3717                        }
     3718                        *out << ", has label " << Labels[Walker->nr];
     3719                        if ((ColorVertexList[Walker->nr] == white) || ((Binder != NULL) && (ColorEdgeList[Binder->nr] == white))) {     // color it if newly discovered and push on stacks (and if within reach!)
     3720                                if ((Binder != NULL) && (ColorEdgeList[Binder->nr] == white)) {
     3721                                        // Binder ought to be set still from last neighbour search
     3722                                        *out << ", coloring bond " << *Binder << " black";
     3723                                        ColorEdgeList[Binder->nr] = black; // mark this bond as used
     3724                                }
     3725                                if (ShortestPathList[Walker->nr] == -1) {
     3726                                        ShortestPathList[Walker->nr] = ShortestPathList[PredecessorList[Walker->nr]->nr]+1;
     3727                                        TouchedStack->Push(Walker); // mark every atom for lists cleanup later, whose shortest path has been changed
     3728                                }
     3729                                if ((ShortestPathList[Walker->nr] < Order) && (ColorVertexList[Walker->nr] != darkgray)) {      // if not already on snake stack
     3730                                        SnakeStack->Push(Walker);
     3731                                        ColorVertexList[Walker->nr] = darkgray; // mark as dark gray of on snake stack
     3732                                }
     3733                        }
     3734                        *out << ", SP of " << ShortestPathList[Walker->nr]      << " and its color is " << GetColor(ColorVertexList[Walker->nr]) << "." << endl;
     3735
     3736                        // then check the stack for a newly stumbled upon fragment
     3737                        if (SnakeStack->ItemCount() == Order) { // is stack full?
     3738                                // store the fragment if it is one and get a removal candidate
     3739                                Removal = StoreFragmentFromStack(out, Root, Walker, Leaflet, SnakeStack, ShortestPathList, SonList, Labels, &FragmentCounter, configuration);
     3740                                // remove the candidate if one was found
     3741                                if (Removal != NULL) {
     3742                                        *out << Verbose(2) << "Removing item " << Removal->Name << " with SP of " << ShortestPathList[Removal->nr] << " from snake stack." << endl;
     3743                                        SnakeStack->RemoveItem(Removal);
     3744                                        ColorVertexList[Removal->nr] = lightgray; // return back to not on snake stack but explored marking
     3745                                        if (Walker == Removal) { // if the current atom is to be removed, we also have to take a step back
     3746                                                Walker = PredecessorList[Removal->nr];
     3747                                                *out << Verbose(2) << "Stepping back to " << Walker->Name << "." << endl;
     3748                                        }
     3749                                }
     3750                        } else
     3751                                Removal = NULL;
     3752
     3753                        // finally, look for a white neighbour as the next Walker
     3754                        Binder = NULL;
     3755                        if ((Removal == NULL) || (Walker != PredecessorList[Removal->nr])) {    // don't look, if a new walker has been set above
     3756                                *out << Verbose(2) << "Snake has currently " << SnakeStack->ItemCount() << " item(s)." << endl;
     3757                                OtherAtom = NULL; // this is actually not needed, every atom has at least one neighbour
     3758                                if (ShortestPathList[Walker->nr] < Order) {
     3759                                        for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
     3760                                                Binder = ListOfBondsPerAtom[Walker->nr][i];
     3761                                                *out << Verbose(2) << "Current bond is " << *Binder << ": ";
     3762                                                OtherAtom = Binder->GetOtherAtom(Walker);
     3763                                                if ((Labels[OtherAtom->nr] != -1) && (Labels[OtherAtom->nr] < Labels[Root->nr])) { // we don't step up to labels bigger than us
     3764                                                        *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl;
     3765                                                        //ColorVertexList[OtherAtom->nr] = lightgray;           // mark as explored
     3766                                                } else { // otherwise check its colour and element
     3767                                                        if (
    37693768#ifdef ADDHYDROGEN
    3770               (OtherAtom->type->Z != 1) &&
     3769                                                        (OtherAtom->type->Z != 1) &&
    37713770#endif
    3772                     (ColorEdgeList[Binder->nr] == white)) {  // skip hydrogen, look for unexplored vertices
    3773                 *out << "Moving along " << GetColor(ColorEdgeList[Binder->nr]) << " bond " << Binder << " to " << ((ColorVertexList[OtherAtom->nr] == white) ? "unexplored" : "explored") << " item: " << OtherAtom->Name << "." << endl;
    3774                 // i find it currently rather sensible to always set the predecessor in order to find one's way back
    3775                 //if (PredecessorList[OtherAtom->nr] == NULL) {
    3776                 PredecessorList[OtherAtom->nr] = Walker;
    3777                 *out << Verbose(3) << "Setting Predecessor of " << OtherAtom->Name << " to " << PredecessorList[OtherAtom->nr]->Name << "." << endl;
    3778                 //} else {
    3779                 //  *out << Verbose(3) << "Predecessor of " << OtherAtom->Name << " is " << PredecessorList[OtherAtom->nr]->Name << "." << endl;
    3780                 //}
    3781                 Walker = OtherAtom;
    3782                 break;
    3783               } else {
    3784                 if (OtherAtom->type->Z == 1)
    3785                   *out << "Links to a hydrogen atom." << endl;
    3786                 else
    3787                   *out << "Bond has not white but " << GetColor(ColorEdgeList[Binder->nr]) << " color." << endl;
    3788               }
    3789             }
    3790                         }
    3791         } else {  // means we have stepped beyond the horizon: Return!
    3792           Walker = PredecessorList[Walker->nr];
    3793           OtherAtom = Walker;
    3794           *out << Verbose(3) << "We have gone too far, stepping back to " << Walker->Name << "." << endl;
    3795         }
    3796                         if (Walker != OtherAtom) {      // if no white neighbours anymore, color it black
    3797           *out << Verbose(2) << "Coloring " << Walker->Name << " black." << endl;
    3798                                 ColorVertexList[Walker->nr] = black;
    3799                                 Walker = PredecessorList[Walker->nr];
    3800                         }
    3801       }
    3802         } while ((Walker != Root) || (ColorVertexList[Root->nr] != black));
    3803     *out << Verbose(2) << "Inner Looping is finished." << endl;
    3804 
    3805     // if we reset all AtomCount atoms, we have again technically O(N^2) ...
    3806     *out << Verbose(2) << "Resetting lists." << endl;
    3807     Walker = NULL;
    3808     Binder = NULL;
    3809     while (!TouchedStack->IsEmpty()) {
    3810       Walker = TouchedStack->PopLast();
    3811       *out << Verbose(3) << "Re-initialising entries of " << *Walker << "." << endl;
    3812       for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++)
    3813         ColorEdgeList[ListOfBondsPerAtom[Walker->nr][i]->nr] = white;
    3814       PredecessorList[Walker->nr] = NULL;
    3815       ColorVertexList[Walker->nr] = white;
    3816       ShortestPathList[Walker->nr] = -1;
    3817     }
    3818   }
    3819   *out << Verbose(1) << "Outer Looping over all vertices is done." << endl;
    3820 
    3821   // copy together
    3822   *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl;
    3823   FragmentList = new MoleculeListClass(FragmentCounter, AtomCount);
    3824   RunningIndex = 0;
    3825   while ((Leaflet != NULL) && (RunningIndex < FragmentCounter))  {
    3826     FragmentList->ListOfMolecules[RunningIndex++] = Leaflet->Leaf;
    3827     Leaflet->Leaf = NULL; // prevent molecule from being removed
    3828     TempLeaf = Leaflet;
    3829     Leaflet = Leaflet->previous;
    3830     delete(TempLeaf);
    3831   };
    3832 
    3833   // free memory and exit
    3834   Free((void **)&PredecessorList, "molecule::CreateListOfUniqueFragmentsOfOrder: **PredecessorList");
    3835   Free((void **)&ShortestPathList, "molecule::CreateListOfUniqueFragmentsOfOrder: *ShortestPathList");
    3836   Free((void **)&Labels, "molecule::CreateListOfUniqueFragmentsOfOrder: *Labels");
    3837   Free((void **)&ColorVertexList, "molecule::CreateListOfUniqueFragmentsOfOrder: *ColorList");
    3838   delete(RootStack);
    3839   delete(TouchedStack);
    3840   delete(SnakeStack);
    3841 
    3842   *out << Verbose(1) << "End of CreateListOfUniqueFragmentsOfOrder." << endl;
    3843   return FragmentList;
     3771                                                                                (ColorEdgeList[Binder->nr] == white)) { // skip hydrogen, look for unexplored vertices
     3772                                                                *out << "Moving along " << GetColor(ColorEdgeList[Binder->nr]) << " bond " << Binder << " to " << ((ColorVertexList[OtherAtom->nr] == white) ? "unexplored" : "explored") << " item: " << OtherAtom->Name << "." << endl;
     3773                                                                // i find it currently rather sensible to always set the predecessor in order to find one's way back
     3774                                                                //if (PredecessorList[OtherAtom->nr] == NULL) {
     3775                                                                PredecessorList[OtherAtom->nr] = Walker;
     3776                                                                *out << Verbose(3) << "Setting Predecessor of " << OtherAtom->Name << " to " << PredecessorList[OtherAtom->nr]->Name << "." << endl;
     3777                                                                //} else {
     3778                                                                //      *out << Verbose(3) << "Predecessor of " << OtherAtom->Name << " is " << PredecessorList[OtherAtom->nr]->Name << "." << endl;
     3779                                                                //}
     3780                                                                Walker = OtherAtom;
     3781                                                                break;
     3782                                                        } else {
     3783                                                                if (OtherAtom->type->Z == 1)
     3784                                                                        *out << "Links to a hydrogen atom." << endl;
     3785                                                                else
     3786                                                                        *out << "Bond has not white but " << GetColor(ColorEdgeList[Binder->nr]) << " color." << endl;
     3787                                                        }
     3788                                                }
     3789                                        }
     3790                                } else {        // means we have stepped beyond the horizon: Return!
     3791                                        Walker = PredecessorList[Walker->nr];
     3792                                        OtherAtom = Walker;
     3793                                        *out << Verbose(3) << "We have gone too far, stepping back to " << Walker->Name << "." << endl;
     3794                                }
     3795                                if (Walker != OtherAtom) {      // if no white neighbours anymore, color it black
     3796                                        *out << Verbose(2) << "Coloring " << Walker->Name << " black." << endl;
     3797                                        ColorVertexList[Walker->nr] = black;
     3798                                        Walker = PredecessorList[Walker->nr];
     3799                                }
     3800                        }
     3801                } while ((Walker != Root) || (ColorVertexList[Root->nr] != black));
     3802                *out << Verbose(2) << "Inner Looping is finished." << endl;
     3803
     3804                // if we reset all AtomCount atoms, we have again technically O(N^2) ...
     3805                *out << Verbose(2) << "Resetting lists." << endl;
     3806                Walker = NULL;
     3807                Binder = NULL;
     3808                while (!TouchedStack->IsEmpty()) {
     3809                        Walker = TouchedStack->PopLast();
     3810                        *out << Verbose(3) << "Re-initialising entries of " << *Walker << "." << endl;
     3811                        for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++)
     3812                                ColorEdgeList[ListOfBondsPerAtom[Walker->nr][i]->nr] = white;
     3813                        PredecessorList[Walker->nr] = NULL;
     3814                        ColorVertexList[Walker->nr] = white;
     3815                        ShortestPathList[Walker->nr] = -1;
     3816                }
     3817        }
     3818        *out << Verbose(1) << "Outer Looping over all vertices is done." << endl;
     3819
     3820        // copy together
     3821        *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl;
     3822        FragmentList = new MoleculeListClass(FragmentCounter, AtomCount);
     3823        RunningIndex = 0;
     3824        while ((Leaflet != NULL) && (RunningIndex < FragmentCounter))   {
     3825                FragmentList->ListOfMolecules[RunningIndex++] = Leaflet->Leaf;
     3826                Leaflet->Leaf = NULL; // prevent molecule from being removed
     3827                TempLeaf = Leaflet;
     3828                Leaflet = Leaflet->previous;
     3829                delete(TempLeaf);
     3830        };
     3831
     3832        // free memory and exit
     3833        Free((void **)&PredecessorList, "molecule::CreateListOfUniqueFragmentsOfOrder: **PredecessorList");
     3834        Free((void **)&ShortestPathList, "molecule::CreateListOfUniqueFragmentsOfOrder: *ShortestPathList");
     3835        Free((void **)&Labels, "molecule::CreateListOfUniqueFragmentsOfOrder: *Labels");
     3836        Free((void **)&ColorVertexList, "molecule::CreateListOfUniqueFragmentsOfOrder: *ColorList");
     3837        delete(RootStack);
     3838        delete(TouchedStack);
     3839        delete(SnakeStack);
     3840
     3841        *out << Verbose(1) << "End of CreateListOfUniqueFragmentsOfOrder." << endl;
     3842        return FragmentList;
    38443843};
    38453844*/
     
    38483847 */
    38493848struct UniqueFragments {
    3850   config *configuration;
    3851   atom *Root;
    3852   Graph *Leaflet;
    3853   KeySet *FragmentSet;
    3854   int ANOVAOrder;
    3855   int FragmentCounter;
    3856   int CurrentIndex;
    3857   double TEFactor;
    3858   int *ShortestPathList;
    3859   bool **UsedList;
    3860   bond **BondsPerSPList;
    3861   int *BondsPerSPCount;
     3849        config *configuration;
     3850        atom *Root;
     3851        Graph *Leaflet;
     3852        KeySet *FragmentSet;
     3853        int ANOVAOrder;
     3854        int FragmentCounter;
     3855        int CurrentIndex;
     3856        double TEFactor;
     3857        int *ShortestPathList;
     3858        bool **UsedList;
     3859        bond **BondsPerSPList;
     3860        int *BondsPerSPCount;
    38623861};
    38633862
    38643863/** From a given set of Bond sorted by Shortest Path distance, create all possible fragments of size \a SetDimension.
    38653864 * -# loops over every possible combination (2^dimension of edge set)
    3866  *  -# inserts current set, if there's still space left
    3867  *    -# yes: calls SPFragmentGenerator with structure, created new edge list and size respective to root dist
     3865 *      -# inserts current set, if there's still space left
     3866 *              -# yes: calls SPFragmentGenerator with structure, created new edge list and size respective to root dist
    38683867ance+1
    3869  *    -# no: stores fragment into keyset list by calling InsertFragmentIntoGraph
    3870  *  -# removes all items added into the snake stack (in UniqueFragments structure) added during level (root
     3868 *              -# no: stores fragment into keyset list by calling InsertFragmentIntoGraph
     3869 *      -# removes all items added into the snake stack (in UniqueFragments structure) added during level (root
    38713870distance) and current set
    38723871 * \param *out output stream for debugging
     
    38783877void molecule::SPFragmentGenerator(ofstream *out, struct UniqueFragments *FragmentSearch, int RootDistance, bond **BondsSet, int SetDimension, int SubOrder)
    38793878{
    3880   atom *OtherWalker = NULL;
    3881   int verbosity = 0; //FragmentSearch->ANOVAOrder-SubOrder;
    3882   int NumCombinations;
    3883   bool bit;
    3884   int bits, TouchedIndex, SubSetDimension, SP, Added;
    3885   int Removal;
    3886   int SpaceLeft;
    3887   int *TouchedList = (int *) Malloc(sizeof(int)*(SubOrder+1), "molecule::SPFragmentGenerator: *TouchedList");
    3888   bond *Binder = NULL;
    3889   bond **BondsList = NULL;
    3890   KeySetTestPair TestKeySetInsert;
    3891 
    3892   NumCombinations = 1 << SetDimension;
    3893 
    3894   // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen
    3895   // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder
    3896   // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden
    3897 
    3898   *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl;
    3899   *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;
    3900 
    3901   // initialised touched list (stores added atoms on this level)
    3902   *out << Verbose(1+verbosity) << "Clearing touched list." << endl;
    3903   for (TouchedIndex=SubOrder+1;TouchedIndex--;)  // empty touched list
    3904     TouchedList[TouchedIndex] = -1;
    3905   TouchedIndex = 0;
    3906 
    3907   // create every possible combination of the endpieces
    3908   *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl;
    3909   for (int i=1;i<NumCombinations;i++) {  // sweep through all power set combinations (skip empty set!)
    3910     // count the set bit of i
    3911     bits = 0;
    3912     for (int j=SetDimension;j--;)
    3913       bits += (i & (1 << j)) >> j;
    3914 
    3915     *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl;
    3916     if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue
    3917       // --1-- add this set of the power set of bond partners to the snake stack
    3918       Added = 0;
    3919       for (int j=0;j<SetDimension;j++) {  // pull out every bit by shifting
    3920         bit = ((i & (1 << j)) != 0);  // mask the bit for the j-th bond
    3921         if (bit) {  // if bit is set, we add this bond partner
    3922                 OtherWalker = BondsSet[j]->rightatom;   // rightatom is always the one more distant, i.e. the one to add
    3923           //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl;
    3924           *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl;
    3925           TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr);
    3926           if (TestKeySetInsert.second) {
    3927             TouchedList[TouchedIndex++] = OtherWalker->nr;  // note as added
    3928             Added++;
    3929           } else {
    3930             *out << Verbose(2+verbosity) << "This was item was already present in the keyset." << endl;
    3931           }
    3932             //FragmentSearch->UsedList[OtherWalker->nr][i] = true;
    3933           //}
    3934         } else {
    3935           *out << Verbose(2+verbosity) << "Not adding." << endl;
    3936         }
    3937       }
    3938 
    3939       SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore
    3940       if (SpaceLeft > 0) {
    3941         *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl;
    3942         if (SubOrder > 1) {    // Due to Added above we have to check extra whether we're not already reaching beyond the desired Order
    3943           // --2-- look at all added end pieces of this combination, construct bond subsets and sweep through a power set of these by recursion
    3944           SP = RootDistance+1;  // this is the next level
    3945           // first count the members in the subset
    3946           SubSetDimension = 0;
    3947           Binder = FragmentSearch->BondsPerSPList[2*SP];                // start node for this level
    3948           while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) {              // compare to end node of this level
    3949             Binder = Binder->next;
    3950             for (int k=TouchedIndex;k--;) {
    3951               if (Binder->Contains(TouchedList[k]))  // if we added this very endpiece
    3952                 SubSetDimension++;
    3953             }
    3954           }
    3955           // then allocate and fill the list
    3956           BondsList = (bond **) Malloc(sizeof(bond *)*SubSetDimension, "molecule::SPFragmentGenerator: **BondsList");
    3957           SubSetDimension = 0;
    3958           Binder = FragmentSearch->BondsPerSPList[2*SP];
    3959           while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) {
    3960             Binder = Binder->next;
    3961             for (int k=0;k<TouchedIndex;k++) {
    3962               if (Binder->leftatom->nr == TouchedList[k])  // leftatom is always the close one
    3963                 BondsList[SubSetDimension++] = Binder;
    3964             }
    3965           }
    3966           *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl;
    3967           SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits);
    3968           Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList");
    3969         }
    3970       } else {
    3971         // --2-- otherwise store the complete fragment
    3972         *out << Verbose(1+verbosity) << "Enough items on stack for a fragment!" << endl;
    3973         // store fragment as a KeySet
    3974         *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: ";
    3975         for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++)
    3976           *out << (*runner) << " ";
    3977         *out << endl;
    3978         //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet))
    3979           //*out << Verbose(0) << "ERROR: The found fragment is not a connected subgraph!" << endl;
    3980         InsertFragmentIntoGraph(out, FragmentSearch);
    3981         //Removal = LookForRemovalCandidate(out, FragmentSearch->FragmentSet, FragmentSearch->ShortestPathList);
    3982         //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration);
    3983       }
    3984 
    3985       // --3-- remove all added items in this level from snake stack
    3986       *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl;
    3987       for(int j=0;j<TouchedIndex;j++) {
    3988         Removal = TouchedList[j];
    3989         *out << Verbose(2+verbosity) << "Removing item nr. " << Removal << " from snake stack." << endl;
    3990         FragmentSearch->FragmentSet->erase(Removal);
    3991         TouchedList[j] = -1;
    3992       }
    3993       *out << Verbose(2) << "Remaining local nr.s on snake stack are: ";
    3994       for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++)
    3995         *out << (*runner) << " ";
    3996       *out << endl;
    3997       TouchedIndex = 0; // set Index to 0 for list of atoms added on this level
    3998     } else {
    3999       *out << Verbose(2+verbosity) << "More atoms to add for this set (" << bits << ") than space left on stack " << SubOrder << ", skipping this set." << endl;
    4000     }
    4001   }
    4002   Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList");
    4003   *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl;
     3879        atom *OtherWalker = NULL;
     3880        int verbosity = 0; //FragmentSearch->ANOVAOrder-SubOrder;
     3881        int NumCombinations;
     3882        bool bit;
     3883        int bits, TouchedIndex, SubSetDimension, SP, Added;
     3884        int Removal;
     3885        int SpaceLeft;
     3886        int *TouchedList = (int *) Malloc(sizeof(int)*(SubOrder+1), "molecule::SPFragmentGenerator: *TouchedList");
     3887        bond *Binder = NULL;
     3888        bond **BondsList = NULL;
     3889        KeySetTestPair TestKeySetInsert;
     3890
     3891        NumCombinations = 1 << SetDimension;
     3892
     3893        // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen
     3894        // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder
     3895        // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden
     3896
     3897        *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl;
     3898        *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;
     3899
     3900        // initialised touched list (stores added atoms on this level)
     3901        *out << Verbose(1+verbosity) << "Clearing touched list." << endl;
     3902        for (TouchedIndex=SubOrder+1;TouchedIndex--;)   // empty touched list
     3903                TouchedList[TouchedIndex] = -1;
     3904        TouchedIndex = 0;
     3905
     3906        // create every possible combination of the endpieces
     3907        *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl;
     3908        for (int i=1;i<NumCombinations;i++) {   // sweep through all power set combinations (skip empty set!)
     3909                // count the set bit of i
     3910                bits = 0;
     3911                for (int j=SetDimension;j--;)
     3912                        bits += (i & (1 << j)) >> j;
     3913
     3914                *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl;
     3915                if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue
     3916                        // --1-- add this set of the power set of bond partners to the snake stack
     3917                        Added = 0;
     3918                        for (int j=0;j<SetDimension;j++) {      // pull out every bit by shifting
     3919                                bit = ((i & (1 << j)) != 0);    // mask the bit for the j-th bond
     3920                                if (bit) {      // if bit is set, we add this bond partner
     3921                                        OtherWalker = BondsSet[j]->rightatom;   // rightatom is always the one more distant, i.e. the one to add
     3922                                        //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl;
     3923                                        *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl;
     3924                                        TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr);
     3925                                        if (TestKeySetInsert.second) {
     3926                                                TouchedList[TouchedIndex++] = OtherWalker->nr;  // note as added
     3927                                                Added++;
     3928                                        } else {
     3929                                                *out << Verbose(2+verbosity) << "This was item was already present in the keyset." << endl;
     3930                                        }
     3931                                                //FragmentSearch->UsedList[OtherWalker->nr][i] = true;
     3932                                        //}
     3933                                } else {
     3934                                        *out << Verbose(2+verbosity) << "Not adding." << endl;
     3935                                }
     3936                        }
     3937
     3938                        SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore
     3939                        if (SpaceLeft > 0) {
     3940                                *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl;
     3941                                if (SubOrder > 1) {             // Due to Added above we have to check extra whether we're not already reaching beyond the desired Order
     3942                                        // --2-- look at all added end pieces of this combination, construct bond subsets and sweep through a power set of these by recursion
     3943                                        SP = RootDistance+1;    // this is the next level
     3944                                        // first count the members in the subset
     3945                                        SubSetDimension = 0;
     3946                                        Binder = FragmentSearch->BondsPerSPList[2*SP];          // start node for this level
     3947                                        while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) {                // compare to end node of this level
     3948                                                Binder = Binder->next;
     3949                                                for (int k=TouchedIndex;k--;) {
     3950                                                        if (Binder->Contains(TouchedList[k]))    // if we added this very endpiece
     3951                                                                SubSetDimension++;
     3952                                                }
     3953                                        }
     3954                                        // then allocate and fill the list
     3955                                        BondsList = (bond **) Malloc(sizeof(bond *)*SubSetDimension, "molecule::SPFragmentGenerator: **BondsList");
     3956                                        SubSetDimension = 0;
     3957                                        Binder = FragmentSearch->BondsPerSPList[2*SP];
     3958                                        while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) {
     3959                                                Binder = Binder->next;
     3960                                                for (int k=0;k<TouchedIndex;k++) {
     3961                                                        if (Binder->leftatom->nr == TouchedList[k])      // leftatom is always the close one
     3962                                                                BondsList[SubSetDimension++] = Binder;
     3963                                                }
     3964                                        }
     3965                                        *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl;
     3966                                        SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits);
     3967                                        Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList");
     3968                                }
     3969                        } else {
     3970                                // --2-- otherwise store the complete fragment
     3971                                *out << Verbose(1+verbosity) << "Enough items on stack for a fragment!" << endl;
     3972                                // store fragment as a KeySet
     3973                                *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: ";
     3974                                for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++)
     3975                                        *out << (*runner) << " ";
     3976                                *out << endl;
     3977                                //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet))
     3978                                        //*out << Verbose(0) << "ERROR: The found fragment is not a connected subgraph!" << endl;
     3979                                InsertFragmentIntoGraph(out, FragmentSearch);
     3980                                //Removal = LookForRemovalCandidate(out, FragmentSearch->FragmentSet, FragmentSearch->ShortestPathList);
     3981                                //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration);
     3982                        }
     3983
     3984                        // --3-- remove all added items in this level from snake stack
     3985                        *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl;
     3986                        for(int j=0;j<TouchedIndex;j++) {
     3987                                Removal = TouchedList[j];
     3988                                *out << Verbose(2+verbosity) << "Removing item nr. " << Removal << " from snake stack." << endl;
     3989                                FragmentSearch->FragmentSet->erase(Removal);
     3990                                TouchedList[j] = -1;
     3991                        }
     3992                        *out << Verbose(2) << "Remaining local nr.s on snake stack are: ";
     3993                        for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++)
     3994                                *out << (*runner) << " ";
     3995                        *out << endl;
     3996                        TouchedIndex = 0; // set Index to 0 for list of atoms added on this level
     3997                } else {
     3998                        *out << Verbose(2+verbosity) << "More atoms to add for this set (" << bits << ") than space left on stack " << SubOrder << ", skipping this set." << endl;
     3999                }
     4000        }
     4001        Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList");
     4002        *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl;
    40044003};
    40054004
     
    40124011bool molecule::CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment)
    40134012{
    4014   atom *Walker = NULL, *Walker2 = NULL;
    4015   bool BondStatus = false;
    4016   int size;
    4017 
    4018   *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl;
    4019   *out << Verbose(2) << "Disconnected atom: ";
    4020 
    4021   // count number of atoms in graph
    4022   size = 0;
    4023   for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++)
    4024     size++;
    4025   if (size > 1)
    4026     for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) {
    4027       Walker = FindAtom(*runner);
    4028       BondStatus = false;
    4029       for(KeySet::iterator runners = Fragment->begin(); runners != Fragment->end(); runners++) {
    4030         Walker2 = FindAtom(*runners);
    4031         for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {
    4032           if (ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker) == Walker2) {
    4033             BondStatus = true;
    4034             break;
    4035           }
    4036           if (BondStatus)
    4037             break;
    4038         }
    4039       }
    4040       if (!BondStatus) {
    4041         *out << (*Walker) << endl;
    4042         return false;
    4043       }
    4044     }
    4045   else {
    4046     *out << "none." << endl;
    4047     return true;
    4048   }
    4049   *out << "none." << endl;
    4050 
    4051   *out << Verbose(1) << "End of CheckForConnectedSubgraph" << endl;
    4052 
    4053   return true;
     4013        atom *Walker = NULL, *Walker2 = NULL;
     4014        bool BondStatus = false;
     4015        int size;
     4016
     4017        *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl;
     4018        *out << Verbose(2) << "Disconnected atom: ";
     4019
     4020        // count number of atoms in graph
     4021        size = 0;
     4022        for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++)
     4023                size++;
     4024        if (size > 1)
     4025                for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) {
     4026                        Walker = FindAtom(*runner);
     4027                        BondStatus = false;
     4028                        for(KeySet::iterator runners = Fragment->begin(); runners != Fragment->end(); runners++) {
     4029                                Walker2 = FindAtom(*runners);
     4030                                for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {
     4031                                        if (ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker) == Walker2) {
     4032                                                BondStatus = true;
     4033                                                break;
     4034                                        }
     4035                                        if (BondStatus)
     4036                                                break;
     4037                                }
     4038                        }
     4039                        if (!BondStatus) {
     4040                                *out << (*Walker) << endl;
     4041                                return false;
     4042                        }
     4043                }
     4044        else {
     4045                *out << "none." << endl;
     4046                return true;
     4047        }
     4048        *out << "none." << endl;
     4049
     4050        *out << Verbose(1) << "End of CheckForConnectedSubgraph" << endl;
     4051
     4052        return true;
    40544053}
    40554054
     
    40714070int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet)
    40724071{
    4073   int SP, AtomKeyNr;
    4074   atom *Walker = NULL, *OtherWalker = NULL, *Predecessor = NULL;
    4075   bond *Binder = NULL;
    4076   bond *CurrentEdge = NULL;
    4077   bond **BondsList = NULL;
    4078   int RootKeyNr = FragmentSearch.Root->GetTrueFather()->nr;
    4079   int Counter = FragmentSearch.FragmentCounter;
    4080   int RemainingWalkers;
    4081 
    4082   *out << endl;
    4083   *out << Verbose(0) << "Begin of PowerSetGenerator with order " << Order << " at Root " << *FragmentSearch.Root << "." << endl;
    4084 
    4085   // prepare Label and SP arrays of the BFS search
    4086   FragmentSearch.ShortestPathList[FragmentSearch.Root->nr] = 0;
    4087 
    4088   // prepare root level (SP = 0) and a loop bond denoting Root
    4089   for (int i=1;i<Order;i++)
    4090     FragmentSearch.BondsPerSPCount[i] = 0;
    4091   FragmentSearch.BondsPerSPCount[0] = 1;
    4092   Binder = new bond(FragmentSearch.Root, FragmentSearch.Root);
    4093   add(Binder, FragmentSearch.BondsPerSPList[1]);
    4094 
    4095   // do a BFS search to fill the SP lists and label the found vertices
    4096   // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into
    4097   // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning
    4098   // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth
    4099   // (EdgeinSPLevel) of this tree ...
    4100   // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence
    4101   // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction.
    4102   *out << endl;
    4103   *out << Verbose(0) << "Starting BFS analysis ..." << endl;
    4104   for (SP = 0; SP < (Order-1); SP++) {
    4105     *out << Verbose(1) << "New SP level reached: " << SP << ", creating new SP list with " << FragmentSearch.BondsPerSPCount[SP] << " item(s)";
    4106     if (SP > 0) {
    4107       *out << ", old level closed with " << FragmentSearch.BondsPerSPCount[SP-1] << " item(s)." << endl;
    4108       FragmentSearch.BondsPerSPCount[SP] = 0;
    4109     } else
    4110       *out << "." << endl;
    4111 
    4112     RemainingWalkers = FragmentSearch.BondsPerSPCount[SP];
    4113     CurrentEdge = FragmentSearch.BondsPerSPList[2*SP];    /// start of this SP level's list
    4114     while (CurrentEdge->next != FragmentSearch.BondsPerSPList[2*SP+1]) {    /// end of this SP level's list
    4115       CurrentEdge = CurrentEdge->next;
    4116       RemainingWalkers--;
    4117       Walker = CurrentEdge->rightatom;    // rightatom is always the one more distant
    4118       Predecessor = CurrentEdge->leftatom;    // ... and leftatom is predecessor
    4119       AtomKeyNr = Walker->nr;
    4120       *out << Verbose(0) << "Current Walker is: " << *Walker << " with nr " << Walker->nr << " and SP of " << SP << ", with " << RemainingWalkers << " remaining walkers on this level." << endl;
    4121       // check for new sp level
    4122       // go through all its bonds
    4123       *out << Verbose(1) << "Going through all bonds of Walker." << endl;
    4124       for (int i=0;i<NumberOfBondsPerAtom[AtomKeyNr];i++) {
    4125         Binder = ListOfBondsPerAtom[AtomKeyNr][i];
    4126         OtherWalker = Binder->GetOtherAtom(Walker);
    4127         if ((RestrictedKeySet.find(OtherWalker->nr) != RestrictedKeySet.end())
    4128   #ifdef ADDHYDROGEN
    4129         && (OtherWalker->type->Z != 1)
    4130   #endif
    4131                                                               ) {  // skip hydrogens and restrict to fragment
    4132           *out << Verbose(2) << "Current partner is " << *OtherWalker << " with nr " << OtherWalker->nr << " in bond " << *Binder << "." << endl;
    4133           // set the label if not set (and push on root stack as well)
    4134           if ((OtherWalker != Predecessor) && (OtherWalker->GetTrueFather()->nr > RootKeyNr)) { // only pass through those with label bigger than Root's
    4135             FragmentSearch.ShortestPathList[OtherWalker->nr] = SP+1;
    4136             *out << Verbose(3) << "Set Shortest Path to " << FragmentSearch.ShortestPathList[OtherWalker->nr] << "." << endl;
    4137             // add the bond in between to the SP list
    4138             Binder = new bond(Walker, OtherWalker); // create a new bond in such a manner, that bond::rightatom is always the one more distant
    4139             add(Binder, FragmentSearch.BondsPerSPList[2*(SP+1)+1]);
    4140             FragmentSearch.BondsPerSPCount[SP+1]++;
    4141             *out << Verbose(3) << "Added its bond to SP list, having now " << FragmentSearch.BondsPerSPCount[SP+1] << " item(s)." << endl;
    4142           } else {
    4143             if (OtherWalker != Predecessor)
    4144               *out << Verbose(3) << "Not passing on, as index of " << *OtherWalker << " " << OtherWalker->GetTrueFather()->nr << " is smaller than that of Root " << RootKeyNr << "." << endl;
    4145             else
    4146               *out << Verbose(3) << "This is my predecessor " << *Predecessor << "." << endl;
    4147           }
    4148         } else *out << Verbose(2) << "Is not in the restricted keyset or skipping hydrogen " << *OtherWalker << "." << endl;
    4149       }
    4150     }
    4151   }
    4152 
    4153   // outputting all list for debugging
    4154   *out << Verbose(0) << "Printing all found lists." << endl;
    4155   for(int i=1;i<Order;i++) {    // skip the root edge in the printing
    4156     Binder = FragmentSearch.BondsPerSPList[2*i];
    4157     *out << Verbose(1) << "Current SP level is " << i << "." << endl;
    4158     while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {
    4159       Binder = Binder->next;
    4160       *out << Verbose(2) << *Binder << endl;
    4161     }
    4162   }
    4163 
    4164   // creating fragments with the found edge sets  (may be done in reverse order, faster)
    4165   SP = -1;  // the Root <-> Root edge must be subtracted!
    4166   for(int i=Order;i--;) { // sum up all found edges
    4167     Binder = FragmentSearch.BondsPerSPList[2*i];
    4168     while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {
    4169       Binder = Binder->next;
    4170       SP ++;
    4171     }
    4172   }
    4173   *out << Verbose(0) << "Total number of edges is " << SP << "." << endl;
    4174   if (SP >= (Order-1)) {
    4175     // start with root (push on fragment stack)
    4176     *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl;
    4177     FragmentSearch.FragmentSet->clear();
    4178     *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl;
    4179     // prepare the subset and call the generator
    4180     BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList");
    4181     BondsList[0] = FragmentSearch.BondsPerSPList[0]->next;  // on SP level 0 there's only the root bond
    4182 
    4183     SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order);
    4184 
    4185     Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList");
    4186   } else {
    4187     *out << Verbose(0) << "Not enough total number of edges to build " << Order << "-body fragments." << endl;
    4188   }
    4189 
    4190   // as FragmentSearch structure is used only once, we don't have to clean it anymore
    4191   // remove root from stack
    4192   *out << Verbose(0) << "Removing root again from stack." << endl;
    4193   FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr);
    4194 
    4195   // free'ing the bonds lists
    4196   *out << Verbose(0) << "Free'ing all found lists. and resetting index lists" << endl;
    4197   for(int i=Order;i--;) {
    4198     *out << Verbose(1) << "Current SP level is " << i << ": ";
    4199     Binder = FragmentSearch.BondsPerSPList[2*i];
    4200     while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {
    4201       Binder = Binder->next;
    4202       // *out << "Removing atom " << Binder->leftatom->nr << " and " << Binder->rightatom->nr << "." << endl; // make sure numbers are local
    4203       FragmentSearch.ShortestPathList[Binder->leftatom->nr] = -1;
    4204       FragmentSearch.ShortestPathList[Binder->rightatom->nr] = -1;
    4205     }
    4206     // delete added bonds
    4207     cleanup(FragmentSearch.BondsPerSPList[2*i], FragmentSearch.BondsPerSPList[2*i+1]);
    4208     // also start and end node
    4209     *out << "cleaned." << endl;
    4210   }
    4211 
    4212   // return list
    4213   *out << Verbose(0) << "End of PowerSetGenerator." << endl;
    4214   return (FragmentSearch.FragmentCounter - Counter);
     4072        int SP, AtomKeyNr;
     4073        atom *Walker = NULL, *OtherWalker = NULL, *Predecessor = NULL;
     4074        bond *Binder = NULL;
     4075        bond *CurrentEdge = NULL;
     4076        bond **BondsList = NULL;
     4077        int RootKeyNr = FragmentSearch.Root->GetTrueFather()->nr;
     4078        int Counter = FragmentSearch.FragmentCounter;
     4079        int RemainingWalkers;
     4080
     4081        *out << endl;
     4082        *out << Verbose(0) << "Begin of PowerSetGenerator with order " << Order << " at Root " << *FragmentSearch.Root << "." << endl;
     4083
     4084        // prepare Label and SP arrays of the BFS search
     4085        FragmentSearch.ShortestPathList[FragmentSearch.Root->nr] = 0;
     4086
     4087        // prepare root level (SP = 0) and a loop bond denoting Root
     4088        for (int i=1;i<Order;i++)
     4089                FragmentSearch.BondsPerSPCount[i] = 0;
     4090        FragmentSearch.BondsPerSPCount[0] = 1;
     4091        Binder = new bond(FragmentSearch.Root, FragmentSearch.Root);
     4092        add(Binder, FragmentSearch.BondsPerSPList[1]);
     4093
     4094        // do a BFS search to fill the SP lists and label the found vertices
     4095        // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into
     4096        // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning
     4097        // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth
     4098        // (EdgeinSPLevel) of this tree ...
     4099        // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence
     4100        // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction.
     4101        *out << endl;
     4102        *out << Verbose(0) << "Starting BFS analysis ..." << endl;
     4103        for (SP = 0; SP < (Order-1); SP++) {
     4104                *out << Verbose(1) << "New SP level reached: " << SP << ", creating new SP list with " << FragmentSearch.BondsPerSPCount[SP] << " item(s)";
     4105                if (SP > 0) {
     4106                        *out << ", old level closed with " << FragmentSearch.BondsPerSPCount[SP-1] << " item(s)." << endl;
     4107                        FragmentSearch.BondsPerSPCount[SP] = 0;
     4108                } else
     4109                        *out << "." << endl;
     4110
     4111                RemainingWalkers = FragmentSearch.BondsPerSPCount[SP];
     4112                CurrentEdge = FragmentSearch.BondsPerSPList[2*SP];              /// start of this SP level's list
     4113                while (CurrentEdge->next != FragmentSearch.BondsPerSPList[2*SP+1]) {            /// end of this SP level's list
     4114                        CurrentEdge = CurrentEdge->next;
     4115                        RemainingWalkers--;
     4116                        Walker = CurrentEdge->rightatom;                // rightatom is always the one more distant
     4117                        Predecessor = CurrentEdge->leftatom;            // ... and leftatom is predecessor
     4118                        AtomKeyNr = Walker->nr;
     4119                        *out << Verbose(0) << "Current Walker is: " << *Walker << " with nr " << Walker->nr << " and SP of " << SP << ", with " << RemainingWalkers << " remaining walkers on this level." << endl;
     4120                        // check for new sp level
     4121                        // go through all its bonds
     4122                        *out << Verbose(1) << "Going through all bonds of Walker." << endl;
     4123                        for (int i=0;i<NumberOfBondsPerAtom[AtomKeyNr];i++) {
     4124                                Binder = ListOfBondsPerAtom[AtomKeyNr][i];
     4125                                OtherWalker = Binder->GetOtherAtom(Walker);
     4126                                if ((RestrictedKeySet.find(OtherWalker->nr) != RestrictedKeySet.end())
     4127        #ifdef ADDHYDROGEN
     4128                                && (OtherWalker->type->Z != 1)
     4129        #endif
     4130                                                                                                                                                                                                                                                        ) {     // skip hydrogens and restrict to fragment
     4131                                        *out << Verbose(2) << "Current partner is " << *OtherWalker << " with nr " << OtherWalker->nr << " in bond " << *Binder << "." << endl;
     4132                                        // set the label if not set (and push on root stack as well)
     4133                                        if ((OtherWalker != Predecessor) && (OtherWalker->GetTrueFather()->nr > RootKeyNr)) { // only pass through those with label bigger than Root's
     4134                                                FragmentSearch.ShortestPathList[OtherWalker->nr] = SP+1;
     4135                                                *out << Verbose(3) << "Set Shortest Path to " << FragmentSearch.ShortestPathList[OtherWalker->nr] << "." << endl;
     4136                                                // add the bond in between to the SP list
     4137                                                Binder = new bond(Walker, OtherWalker); // create a new bond in such a manner, that bond::rightatom is always the one more distant
     4138                                                add(Binder, FragmentSearch.BondsPerSPList[2*(SP+1)+1]);
     4139                                                FragmentSearch.BondsPerSPCount[SP+1]++;
     4140                                                *out << Verbose(3) << "Added its bond to SP list, having now " << FragmentSearch.BondsPerSPCount[SP+1] << " item(s)." << endl;
     4141                                        } else {
     4142                                                if (OtherWalker != Predecessor)
     4143                                                        *out << Verbose(3) << "Not passing on, as index of " << *OtherWalker << " " << OtherWalker->GetTrueFather()->nr << " is smaller than that of Root " << RootKeyNr << "." << endl;
     4144                                                else
     4145                                                        *out << Verbose(3) << "This is my predecessor " << *Predecessor << "." << endl;
     4146                                        }
     4147                                } else *out << Verbose(2) << "Is not in the restricted keyset or skipping hydrogen " << *OtherWalker << "." << endl;
     4148                        }
     4149                }
     4150        }
     4151
     4152        // outputting all list for debugging
     4153        *out << Verbose(0) << "Printing all found lists." << endl;
     4154        for(int i=1;i<Order;i++) {              // skip the root edge in the printing
     4155                Binder = FragmentSearch.BondsPerSPList[2*i];
     4156                *out << Verbose(1) << "Current SP level is " << i << "." << endl;
     4157                while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {
     4158                        Binder = Binder->next;
     4159                        *out << Verbose(2) << *Binder << endl;
     4160                }
     4161        }
     4162
     4163        // creating fragments with the found edge sets  (may be done in reverse order, faster)
     4164        SP = -1;        // the Root <-> Root edge must be subtracted!
     4165        for(int i=Order;i--;) { // sum up all found edges
     4166                Binder = FragmentSearch.BondsPerSPList[2*i];
     4167                while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {
     4168                        Binder = Binder->next;
     4169                        SP ++;
     4170                }
     4171        }
     4172        *out << Verbose(0) << "Total number of edges is " << SP << "." << endl;
     4173        if (SP >= (Order-1)) {
     4174                // start with root (push on fragment stack)
     4175                *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl;
     4176                FragmentSearch.FragmentSet->clear();
     4177                *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl;
     4178                // prepare the subset and call the generator
     4179                BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList");
     4180                BondsList[0] = FragmentSearch.BondsPerSPList[0]->next;  // on SP level 0 there's only the root bond
     4181
     4182                SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order);
     4183
     4184                Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList");
     4185        } else {
     4186                *out << Verbose(0) << "Not enough total number of edges to build " << Order << "-body fragments." << endl;
     4187        }
     4188
     4189        // as FragmentSearch structure is used only once, we don't have to clean it anymore
     4190        // remove root from stack
     4191        *out << Verbose(0) << "Removing root again from stack." << endl;
     4192        FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr);
     4193
     4194        // free'ing the bonds lists
     4195        *out << Verbose(0) << "Free'ing all found lists. and resetting index lists" << endl;
     4196        for(int i=Order;i--;) {
     4197                *out << Verbose(1) << "Current SP level is " << i << ": ";
     4198                Binder = FragmentSearch.BondsPerSPList[2*i];
     4199                while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {
     4200                        Binder = Binder->next;
     4201                        // *out << "Removing atom " << Binder->leftatom->nr << " and " << Binder->rightatom->nr << "." << endl; // make sure numbers are local
     4202                        FragmentSearch.ShortestPathList[Binder->leftatom->nr] = -1;
     4203                        FragmentSearch.ShortestPathList[Binder->rightatom->nr] = -1;
     4204                }
     4205                // delete added bonds
     4206                cleanup(FragmentSearch.BondsPerSPList[2*i], FragmentSearch.BondsPerSPList[2*i+1]);
     4207                // also start and end node
     4208                *out << "cleaned." << endl;
     4209        }
     4210
     4211        // return list
     4212        *out << Verbose(0) << "End of PowerSetGenerator." << endl;
     4213        return (FragmentSearch.FragmentCounter - Counter);
    42154214};
    42164215
     
    42234222void molecule::ScanForPeriodicCorrection(ofstream *out)
    42244223{
    4225   bond *Binder = NULL;
    4226   bond *OtherBinder = NULL;
    4227   atom *Walker = NULL;
    4228   atom *OtherWalker = NULL;
    4229   double *matrix = ReturnFullMatrixforSymmetric(cell_size);
    4230   enum Shading *ColorList = NULL;
    4231   double tmp;
    4232   Vector Translationvector;
    4233   //class StackClass<atom *> *CompStack = NULL;
    4234   class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);
    4235   bool flag = true;
    4236 
    4237   *out << Verbose(2) << "Begin of ScanForPeriodicCorrection." << endl;
    4238 
    4239   ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::ScanForPeriodicCorrection: *ColorList");
    4240   while (flag) {
    4241     // remove bonds that are beyond bonddistance
    4242     for(int i=NDIM;i--;)
    4243       Translationvector.x[i] = 0.;
    4244     // scan all bonds
    4245     Binder = first;
    4246     flag = false;
    4247     while ((!flag) && (Binder->next != last)) {
    4248       Binder = Binder->next;
    4249       for (int i=NDIM;i--;) {
    4250         tmp = fabs(Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]);
    4251         //*out << Verbose(3) << "Checking " << i << "th distance of " << *Binder->leftatom << " to " << *Binder->rightatom << ": " << tmp << "." << endl;
    4252         if (tmp > BondDistance) {
    4253           OtherBinder = Binder->next; // note down binding partner for later re-insertion
    4254           unlink(Binder);  // unlink bond
    4255           *out << Verbose(2) << "Correcting at bond " << *Binder << "." << endl;
    4256           flag = true;
    4257           break;
    4258         }
    4259       }
    4260     }
    4261     if (flag) {
    4262       // create translation vector from their periodically modified distance
    4263       for (int i=NDIM;i--;) {
    4264         tmp = Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i];
    4265         if (fabs(tmp) > BondDistance)
    4266           Translationvector.x[i] = (tmp < 0) ? +1. : -1.;
    4267       }
    4268       Translationvector.MatrixMultiplication(matrix);
    4269       //*out << Verbose(3) << "Translation vector is ";
    4270       Translationvector.Output(out);
    4271       *out << endl;
    4272       // apply to all atoms of first component via BFS
    4273       for (int i=AtomCount;i--;)
    4274         ColorList[i] = white;
    4275       AtomStack->Push(Binder->leftatom);
    4276       while (!AtomStack->IsEmpty()) {
    4277         Walker = AtomStack->PopFirst();
    4278         //*out << Verbose (3) << "Current Walker is: " << *Walker << "." << endl;
    4279         ColorList[Walker->nr] = black;    // mark as explored
    4280         Walker->x.AddVector(&Translationvector); // translate
    4281         for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {  // go through all binding partners
    4282           if (ListOfBondsPerAtom[Walker->nr][i] != Binder) {
    4283             OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
    4284             if (ColorList[OtherWalker->nr] == white) {
    4285               AtomStack->Push(OtherWalker); // push if yet unexplored
    4286             }
    4287           }
    4288         }
    4289       }
    4290       // re-add bond
    4291       link(Binder, OtherBinder);
    4292     } else {
    4293       *out << Verbose(3) << "No corrections for this fragment." << endl;
    4294     }
    4295     //delete(CompStack);
    4296   }
    4297 
    4298   // free allocated space from ReturnFullMatrixforSymmetric()
    4299   delete(AtomStack);
    4300   Free((void **)&ColorList, "molecule::ScanForPeriodicCorrection: *ColorList");
    4301   Free((void **)&matrix, "molecule::ScanForPeriodicCorrection: *matrix");
    4302   *out << Verbose(2) << "End of ScanForPeriodicCorrection." << endl;
     4224        bond *Binder = NULL;
     4225        bond *OtherBinder = NULL;
     4226        atom *Walker = NULL;
     4227        atom *OtherWalker = NULL;
     4228        double *matrix = ReturnFullMatrixforSymmetric(cell_size);
     4229        enum Shading *ColorList = NULL;
     4230        double tmp;
     4231        Vector Translationvector;
     4232        //class StackClass<atom *> *CompStack = NULL;
     4233        class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);
     4234        bool flag = true;
     4235
     4236        *out << Verbose(2) << "Begin of ScanForPeriodicCorrection." << endl;
     4237
     4238        ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::ScanForPeriodicCorrection: *ColorList");
     4239        while (flag) {
     4240                // remove bonds that are beyond bonddistance
     4241                for(int i=NDIM;i--;)
     4242                        Translationvector.x[i] = 0.;
     4243                // scan all bonds
     4244                Binder = first;
     4245                flag = false;
     4246                while ((!flag) && (Binder->next != last)) {
     4247                        Binder = Binder->next;
     4248                        for (int i=NDIM;i--;) {
     4249                                tmp = fabs(Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]);
     4250                                //*out << Verbose(3) << "Checking " << i << "th distance of " << *Binder->leftatom << " to " << *Binder->rightatom << ": " << tmp << "." << endl;
     4251                                if (tmp > BondDistance) {
     4252                                        OtherBinder = Binder->next; // note down binding partner for later re-insertion
     4253                                        unlink(Binder); // unlink bond
     4254                                        *out << Verbose(2) << "Correcting at bond " << *Binder << "." << endl;
     4255                                        flag = true;
     4256                                        break;
     4257                                }
     4258                        }
     4259                }
     4260                if (flag) {
     4261                        // create translation vector from their periodically modified distance
     4262                        for (int i=NDIM;i--;) {
     4263                                tmp = Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i];
     4264                                if (fabs(tmp) > BondDistance)
     4265                                        Translationvector.x[i] = (tmp < 0) ? +1. : -1.;
     4266                        }
     4267                        Translationvector.MatrixMultiplication(matrix);
     4268                        //*out << Verbose(3) << "Translation vector is ";
     4269                        Translationvector.Output(out);
     4270                        *out << endl;
     4271                        // apply to all atoms of first component via BFS
     4272                        for (int i=AtomCount;i--;)
     4273                                ColorList[i] = white;
     4274                        AtomStack->Push(Binder->leftatom);
     4275                        while (!AtomStack->IsEmpty()) {
     4276                                Walker = AtomStack->PopFirst();
     4277                                //*out << Verbose (3) << "Current Walker is: " << *Walker << "." << endl;
     4278                                ColorList[Walker->nr] = black;          // mark as explored
     4279                                Walker->x.AddVector(&Translationvector); // translate
     4280                                for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {  // go through all binding partners
     4281                                        if (ListOfBondsPerAtom[Walker->nr][i] != Binder) {
     4282                                                OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
     4283                                                if (ColorList[OtherWalker->nr] == white) {
     4284                                                        AtomStack->Push(OtherWalker); // push if yet unexplored
     4285                                                }
     4286                                        }
     4287                                }
     4288                        }
     4289                        // re-add bond
     4290                        link(Binder, OtherBinder);
     4291                } else {
     4292                        *out << Verbose(3) << "No corrections for this fragment." << endl;
     4293                }
     4294                //delete(CompStack);
     4295        }
     4296
     4297        // free allocated space from ReturnFullMatrixforSymmetric()
     4298        delete(AtomStack);
     4299        Free((void **)&ColorList, "molecule::ScanForPeriodicCorrection: *ColorList");
     4300        Free((void **)&matrix, "molecule::ScanForPeriodicCorrection: *matrix");
     4301        *out << Verbose(2) << "End of ScanForPeriodicCorrection." << endl;
    43034302};
    43044303
     
    43094308double * molecule::ReturnFullMatrixforSymmetric(double *symm)
    43104309{
    4311   double *matrix = (double *) Malloc(sizeof(double)*NDIM*NDIM, "molecule::ReturnFullMatrixforSymmetric: *matrix");
    4312   matrix[0] = symm[0];
    4313   matrix[1] = symm[1];
    4314   matrix[2] = symm[3];
    4315   matrix[3] = symm[1];
    4316   matrix[4] = symm[2];
    4317   matrix[5] = symm[4];
    4318   matrix[6] = symm[3];
    4319   matrix[7] = symm[4];
    4320   matrix[8] = symm[5];
    4321   return matrix;
     4310        double *matrix = (double *) Malloc(sizeof(double)*NDIM*NDIM, "molecule::ReturnFullMatrixforSymmetric: *matrix");
     4311        matrix[0] = symm[0];
     4312        matrix[1] = symm[1];
     4313        matrix[2] = symm[3];
     4314        matrix[3] = symm[1];
     4315        matrix[4] = symm[2];
     4316        matrix[5] = symm[4];
     4317        matrix[6] = symm[3];
     4318        matrix[7] = symm[4];
     4319        matrix[8] = symm[5];
     4320        return matrix;
    43224321};
    43234322
    43244323bool KeyCompare::operator() (const KeySet SubgraphA, const KeySet SubgraphB) const
    43254324{
    4326   //cout << "my check is used." << endl;
    4327   if (SubgraphA.size() < SubgraphB.size()) {
    4328     return true;
    4329   } else {
    4330     if (SubgraphA.size() > SubgraphB.size()) {
    4331       return false;
    4332     } else {
    4333       KeySet::iterator IteratorA = SubgraphA.begin();
    4334       KeySet::iterator IteratorB = SubgraphB.begin();
    4335       while ((IteratorA != SubgraphA.end()) && (IteratorB != SubgraphB.end())) {
    4336         if ((*IteratorA) <  (*IteratorB))
    4337           return true;
    4338         else if ((*IteratorA) > (*IteratorB)) {
    4339             return false;
    4340           } // else, go on to next index
    4341         IteratorA++;
    4342         IteratorB++;
    4343       } // end of while loop
    4344     }// end of check in case of equal sizes
    4345   }
    4346   return false; // if we reach this point, they are equal
     4325        //cout << "my check is used." << endl;
     4326        if (SubgraphA.size() < SubgraphB.size()) {
     4327                return true;
     4328        } else {
     4329                if (SubgraphA.size() > SubgraphB.size()) {
     4330                        return false;
     4331                } else {
     4332                        KeySet::iterator IteratorA = SubgraphA.begin();
     4333                        KeySet::iterator IteratorB = SubgraphB.begin();
     4334                        while ((IteratorA != SubgraphA.end()) && (IteratorB != SubgraphB.end())) {
     4335                                if ((*IteratorA) <      (*IteratorB))
     4336                                        return true;
     4337                                else if ((*IteratorA) > (*IteratorB)) {
     4338                                                return false;
     4339                                        } // else, go on to next index
     4340                                IteratorA++;
     4341                                IteratorB++;
     4342                        } // end of while loop
     4343                }// end of check in case of equal sizes
     4344        }
     4345        return false; // if we reach this point, they are equal
    43474346};
    43484347
    43494348//bool operator < (KeySet SubgraphA, KeySet SubgraphB)
    43504349//{
    4351 //  return KeyCompare(SubgraphA, SubgraphB);
     4350//      return KeyCompare(SubgraphA, SubgraphB);
    43524351//};
    43534352
     
    43614360inline void InsertFragmentIntoGraph(ofstream *out, struct UniqueFragments *Fragment)
    43624361{
    4363   GraphTestPair testGraphInsert;
    4364 
    4365   testGraphInsert = Fragment->Leaflet->insert(GraphPair (*Fragment->FragmentSet,pair<int,double>(Fragment->FragmentCounter,Fragment->TEFactor)));  // store fragment number and current factor
    4366   if (testGraphInsert.second) {
    4367     *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " successfully inserted." << endl;
    4368     Fragment->FragmentCounter++;
    4369   } else {
    4370     *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;
    4371     ((*(testGraphInsert.first)).second).second += Fragment->TEFactor;  // increase the "created" counter
    4372     *out << Verbose(2) << "New factor is " << ((*(testGraphInsert.first)).second).second << "." << endl;
    4373   }
     4362        GraphTestPair testGraphInsert;
     4363
     4364        testGraphInsert = Fragment->Leaflet->insert(GraphPair (*Fragment->FragmentSet,pair<int,double>(Fragment->FragmentCounter,Fragment->TEFactor))); // store fragment number and current factor
     4365        if (testGraphInsert.second) {
     4366                *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " successfully inserted." << endl;
     4367                Fragment->FragmentCounter++;
     4368        } else {
     4369                *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;
     4370                ((*(testGraphInsert.first)).second).second += Fragment->TEFactor;       // increase the "created" counter
     4371                *out << Verbose(2) << "New factor is " << ((*(testGraphInsert.first)).second).second << "." << endl;
     4372        }
    43744373};
    43754374//void inline InsertIntoGraph(ofstream *out, KeyStack &stack, Graph &graph, int *counter, double factor)
    43764375//{
    4377 //  // copy stack contents to set and call overloaded function again
    4378 //  KeySet set;
    4379 //  for(KeyStack::iterator runner = stack.begin(); runner != stack.begin(); runner++)
    4380 //    set.insert((*runner));
    4381 //  InsertIntoGraph(out, set, graph, counter, factor);
     4376//      // copy stack contents to set and call overloaded function again
     4377//      KeySet set;
     4378//      for(KeyStack::iterator runner = stack.begin(); runner != stack.begin(); runner++)
     4379//              set.insert((*runner));
     4380//      InsertIntoGraph(out, set, graph, counter, factor);
    43824381//};
    43834382
     
    43904389inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter)
    43914390{
    4392   GraphTestPair testGraphInsert;
    4393 
    4394   for(Graph::iterator runner = graph2.begin(); runner != graph2.end(); runner++) {
    4395     testGraphInsert = graph1.insert(GraphPair ((*runner).first,pair<int,double>((*counter)++,((*runner).second).second)));  // store fragment number and current factor
    4396     if (testGraphInsert.second) {
    4397       *out << Verbose(2) << "KeySet " << (*counter)-1 << " successfully inserted." << endl;
    4398     } else {
    4399       *out << Verbose(2) << "KeySet " << (*counter)-1 << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;
    4400       ((*(testGraphInsert.first)).second).second += (*runner).second.second;
    4401       *out << Verbose(2) << "New factor is " << (*(testGraphInsert.first)).second.second << "." << endl;
    4402     }
    4403   }
     4391        GraphTestPair testGraphInsert;
     4392
     4393        for(Graph::iterator runner = graph2.begin(); runner != graph2.end(); runner++) {
     4394                testGraphInsert = graph1.insert(GraphPair ((*runner).first,pair<int,double>((*counter)++,((*runner).second).second)));  // store fragment number and current factor
     4395                if (testGraphInsert.second) {
     4396                        *out << Verbose(2) << "KeySet " << (*counter)-1 << " successfully inserted." << endl;
     4397                } else {
     4398                        *out << Verbose(2) << "KeySet " << (*counter)-1 << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;
     4399                        ((*(testGraphInsert.first)).second).second += (*runner).second.second;
     4400                        *out << Verbose(2) << "New factor is " << (*(testGraphInsert.first)).second.second << "." << endl;
     4401                }
     4402        }
    44044403};
    44054404
     
    44084407 * -# constructs a complete keyset of the molecule
    44094408 * -# In a loop over all possible roots from the given rootstack
    4410  *  -# increases order of root site
    4411  *  -# calls PowerSetGenerator with this order, the complete keyset and the rootkeynr
    4412  *  -# for all consecutive lower levels PowerSetGenerator is called with the suborder, the higher order keyset
     4409 *      -# increases order of root site
     4410 *      -# calls PowerSetGenerator with this order, the complete keyset and the rootkeynr
     4411 *      -# for all consecutive lower levels PowerSetGenerator is called with the suborder, the higher order keyset
    44134412as the restricted one and each site in the set as the root)
    4414  *  -# these are merged into a fragment list of keysets
     4413 *      -# these are merged into a fragment list of keysets
    44154414 * -# All fragment lists (for all orders, i.e. from all destination fields) are merged into one list for return
    44164415 * Important only is that we create all fragments, it is not important if we create them more than once
     
    44244423void molecule::FragmentBOSSANOVA(ofstream *out, Graph *&FragmentList, KeyStack &RootStack, int *MinimumRingSize)
    44254424{
    4426   Graph ***FragmentLowerOrdersList = NULL;
    4427   int NumLevels, NumMolecules, TotalNumMolecules = 0, *NumMoleculesOfOrder = NULL;
    4428   int counter = 0, Order;
    4429   int UpgradeCount = RootStack.size();
    4430   KeyStack FragmentRootStack;
    4431   int RootKeyNr, RootNr;
    4432   struct UniqueFragments FragmentSearch;
    4433 
    4434   *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl;
    4435 
    4436   // FragmentLowerOrdersList is a 2D-array of pointer to MoleculeListClass objects, one dimension represents the ANOVA expansion of a single order (i.e. 5)
    4437   // with all needed lower orders that are subtracted, the other dimension is the BondOrder (i.e. from 1 to 5)
    4438   NumMoleculesOfOrder = (int *) Malloc(sizeof(int)*UpgradeCount, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder");
    4439   FragmentLowerOrdersList = (Graph ***) Malloc(sizeof(Graph **)*UpgradeCount, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList");
    4440 
    4441   // initialise the fragments structure
    4442   FragmentSearch.ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::PowerSetGenerator: *ShortestPathList");
    4443   FragmentSearch.FragmentCounter = 0;
    4444   FragmentSearch.FragmentSet = new KeySet;
    4445   FragmentSearch.Root = FindAtom(RootKeyNr);
    4446   for (int i=AtomCount;i--;) {
    4447     FragmentSearch.ShortestPathList[i] = -1;
    4448   }
    4449 
    4450   // Construct the complete KeySet which we need for topmost level only (but for all Roots)
    4451   atom *Walker = start;
    4452   KeySet CompleteMolecule;
    4453   while (Walker->next != end) {
    4454     Walker = Walker->next;
    4455     CompleteMolecule.insert(Walker->GetTrueFather()->nr);
    4456   }
    4457 
    4458   // 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
    4459   // 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),
    4460   // hence we have overall four 2th order levels for splitting. This also allows for putting all into a single array (FragmentLowerOrdersList[])
    4461   // 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)
    4462   RootNr = 0;  // counts through the roots in RootStack
    4463   while ((RootNr < UpgradeCount) && (!RootStack.empty())) {
    4464     RootKeyNr = RootStack.front();
    4465     RootStack.pop_front();
    4466     Walker = FindAtom(RootKeyNr);
    4467     // check cyclic lengths
    4468     //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) {
    4469     //  *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;
    4470     //} else
    4471     {
    4472       // increase adaptive order by one
    4473       Walker->GetTrueFather()->AdaptiveOrder++;
    4474       Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder;
    4475 
    4476       // initialise Order-dependent entries of UniqueFragments structure
    4477       FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList");
    4478       FragmentSearch.BondsPerSPCount = (int *) Malloc(sizeof(int)*Order, "molecule::PowerSetGenerator: *BondsPerSPCount");
    4479       for (int i=Order;i--;) {
    4480         FragmentSearch.BondsPerSPList[2*i] = new bond();    // start node
    4481         FragmentSearch.BondsPerSPList[2*i+1] = new bond();  // end node
    4482         FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1];    // intertwine these two
    4483         FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i];
    4484         FragmentSearch.BondsPerSPCount[i] = 0;
    4485       }
    4486 
    4487       // allocate memory for all lower level orders in this 1D-array of ptrs
    4488       NumLevels = 1 << (Order-1); // (int)pow(2,Order);
    4489       FragmentLowerOrdersList[RootNr] = (Graph **) Malloc(sizeof(Graph *)*NumLevels, "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]");
    4490       for (int i=0;i<NumLevels;i++)
    4491         FragmentLowerOrdersList[RootNr][i] = NULL;
    4492 
    4493       // create top order where nothing is reduced
    4494       *out << Verbose(0) << "==============================================================================================================" << endl;
    4495       *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << "
    4496 
    4497       // Create list of Graphs of current Bond Order (i.e. F_{ij})
    4498       FragmentLowerOrdersList[RootNr][0] =  new Graph;
    4499       FragmentSearch.TEFactor = 1.;
    4500       FragmentSearch.Leaflet = FragmentLowerOrdersList[RootNr][0];      // set to insertion graph
    4501       FragmentSearch.Root = Walker;
    4502       NumMoleculesOfOrder[RootNr] = PowerSetGenerator(out, Walker->AdaptiveOrder, FragmentSearch, CompleteMolecule);
    4503       *out << Verbose(1) << "Number of resulting KeySets is: " << NumMoleculesOfOrder[RootNr] << "." << endl;
    4504       if (NumMoleculesOfOrder[RootNr] != 0) {
    4505         NumMolecules = 0;
    4506 
    4507         // we don't have to dive into suborders! These keysets are all already created on lower orders!
    4508         // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed)
    4509 
    4510 //        if ((NumLevels >> 1) > 0) {
    4511 //          // create lower order fragments
    4512 //          *out << Verbose(0) << "Creating list of unique fragments of lower Bond Order terms to be subtracted." << endl;
    4513 //          Order = Walker->AdaptiveOrder;
    4514 //          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)
    4515 //            // step down to next order at (virtual) boundary of powers of 2 in array
    4516 //            while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order))
    4517 //              Order--;
    4518 //            *out << Verbose(0) << "Current Order is: " << Order << "." << endl;
    4519 //            for (int SubOrder=Order-1;SubOrder>0;SubOrder--) {
    4520 //              int dest = source + (1 << (Walker->AdaptiveOrder-(SubOrder+1)));
    4521 //              *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl;
    4522 //              *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl;
     4425        Graph ***FragmentLowerOrdersList = NULL;
     4426        int NumLevels, NumMolecules, TotalNumMolecules = 0, *NumMoleculesOfOrder = NULL;
     4427        int counter = 0, Order;
     4428        int UpgradeCount = RootStack.size();
     4429        KeyStack FragmentRootStack;
     4430        int RootKeyNr, RootNr;
     4431        struct UniqueFragments FragmentSearch;
     4432
     4433        *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl;
     4434
     4435        // FragmentLowerOrdersList is a 2D-array of pointer to MoleculeListClass objects, one dimension represents the ANOVA expansion of a single order (i.e. 5)
     4436        // with all needed lower orders that are subtracted, the other dimension is the BondOrder (i.e. from 1 to 5)
     4437        NumMoleculesOfOrder = (int *) Malloc(sizeof(int)*UpgradeCount, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder");
     4438        FragmentLowerOrdersList = (Graph ***) Malloc(sizeof(Graph **)*UpgradeCount, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList");
     4439
     4440        // initialise the fragments structure
     4441        FragmentSearch.ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::PowerSetGenerator: *ShortestPathList");
     4442        FragmentSearch.FragmentCounter = 0;
     4443        FragmentSearch.FragmentSet = new KeySet;
     4444        FragmentSearch.Root = FindAtom(RootKeyNr);
     4445        for (int i=AtomCount;i--;) {
     4446                FragmentSearch.ShortestPathList[i] = -1;
     4447        }
     4448
     4449        // Construct the complete KeySet which we need for topmost level only (but for all Roots)
     4450        atom *Walker = start;
     4451        KeySet CompleteMolecule;
     4452        while (Walker->next != end) {
     4453                Walker = Walker->next;
     4454                CompleteMolecule.insert(Walker->GetTrueFather()->nr);
     4455        }
     4456
     4457        // 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
     4458        // 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),
     4459        // hence we have overall four 2th order levels for splitting. This also allows for putting all into a single array (FragmentLowerOrdersList[])
     4460        // 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)
     4461        RootNr = 0;      // counts through the roots in RootStack
     4462        while ((RootNr < UpgradeCount) && (!RootStack.empty())) {
     4463                RootKeyNr = RootStack.front();
     4464                RootStack.pop_front();
     4465                Walker = FindAtom(RootKeyNr);
     4466                // check cyclic lengths
     4467                //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) {
     4468                //      *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;
     4469                //} else
     4470                {
     4471                        // increase adaptive order by one
     4472                        Walker->GetTrueFather()->AdaptiveOrder++;
     4473                        Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder;
     4474
     4475                        // initialise Order-dependent entries of UniqueFragments structure
     4476                        FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList");
     4477                        FragmentSearch.BondsPerSPCount = (int *) Malloc(sizeof(int)*Order, "molecule::PowerSetGenerator: *BondsPerSPCount");
     4478                        for (int i=Order;i--;) {
     4479                                FragmentSearch.BondsPerSPList[2*i] = new bond();                // start node
     4480                                FragmentSearch.BondsPerSPList[2*i+1] = new bond();      // end node
     4481                                FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1];                // intertwine these two
     4482                                FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i];
     4483                                FragmentSearch.BondsPerSPCount[i] = 0;
     4484                        }
     4485
     4486                        // allocate memory for all lower level orders in this 1D-array of ptrs
     4487                        NumLevels = 1 << (Order-1); // (int)pow(2,Order);
     4488                        FragmentLowerOrdersList[RootNr] = (Graph **) Malloc(sizeof(Graph *)*NumLevels, "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]");
     4489                        for (int i=0;i<NumLevels;i++)
     4490                                FragmentLowerOrdersList[RootNr][i] = NULL;
     4491
     4492                        // create top order where nothing is reduced
     4493                        *out << Verbose(0) << "==============================================================================================================" << endl;
     4494                        *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << "
     4495
     4496                        // Create list of Graphs of current Bond Order (i.e. F_{ij})
     4497                        FragmentLowerOrdersList[RootNr][0] =    new Graph;
     4498                        FragmentSearch.TEFactor = 1.;
     4499                        FragmentSearch.Leaflet = FragmentLowerOrdersList[RootNr][0];                    // set to insertion graph
     4500                        FragmentSearch.Root = Walker;
     4501                        NumMoleculesOfOrder[RootNr] = PowerSetGenerator(out, Walker->AdaptiveOrder, FragmentSearch, CompleteMolecule);
     4502                        *out << Verbose(1) << "Number of resulting KeySets is: " << NumMoleculesOfOrder[RootNr] << "." << endl;
     4503                        if (NumMoleculesOfOrder[RootNr] != 0) {
     4504                                NumMolecules = 0;
     4505
     4506                                // we don't have to dive into suborders! These keysets are all already created on lower orders!
     4507                                // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed)
     4508
     4509//                              if ((NumLevels >> 1) > 0) {
     4510//                                      // create lower order fragments
     4511//                                      *out << Verbose(0) << "Creating list of unique fragments of lower Bond Order terms to be subtracted." << endl;
     4512//                                      Order = Walker->AdaptiveOrder;
     4513//                                      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)
     4514//                                              // step down to next order at (virtual) boundary of powers of 2 in array
     4515//                                              while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order))
     4516//                                                      Order--;
     4517//                                              *out << Verbose(0) << "Current Order is: " << Order << "." << endl;
     4518//                                              for (int SubOrder=Order-1;SubOrder>0;SubOrder--) {
     4519//                                                      int dest = source + (1 << (Walker->AdaptiveOrder-(SubOrder+1)));
     4520//                                                      *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl;
     4521//                                                      *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl;
    45234522//
    4524 //              // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules
    4525 //              //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl;
    4526 //              //NumMolecules = 0;
    4527 //              FragmentLowerOrdersList[RootNr][dest] = new Graph;
    4528 //              for(Graph::iterator runner = (*FragmentLowerOrdersList[RootNr][source]).begin();runner != (*FragmentLowerOrdersList[RootNr][source]).end(); runner++) {
    4529 //                for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) {
    4530 //                  Graph TempFragmentList;
    4531 //                  FragmentSearch.TEFactor = -(*runner).second.second;
    4532 //                  FragmentSearch.Leaflet = &TempFragmentList;      // set to insertion graph
    4533 //                  FragmentSearch.Root = FindAtom(*sprinter);
    4534 //                  NumMoleculesOfOrder[RootNr] += PowerSetGenerator(out, SubOrder, FragmentSearch, (*runner).first);
    4535 //                  // insert new keysets FragmentList into FragmentLowerOrdersList[Walker->AdaptiveOrder-1][dest]
    4536 //                  *out << Verbose(1) << "Merging resulting key sets with those present in destination " << dest << "." << endl;
    4537 //                  InsertGraphIntoGraph(out, *FragmentLowerOrdersList[RootNr][dest], TempFragmentList, &NumMolecules);
    4538 //                }
    4539 //              }
    4540 //              *out << Verbose(1) << "Number of resulting molecules for SubOrder " << SubOrder << " is: " << NumMolecules << "." << endl;
    4541 //            }
    4542 //          }
    4543 //        }
    4544       } else {
    4545         Walker->GetTrueFather()->MaxOrder = true;
    4546 //        *out << Verbose(1) << "Hence, we don't dive into SubOrders ... " << endl;
    4547       }
    4548       // now, we have completely filled each cell of FragmentLowerOrdersList[] for the current Walker->AdaptiveOrder
    4549       //NumMoleculesOfOrder[Walker->AdaptiveOrder-1] = NumMolecules;
    4550       TotalNumMolecules += NumMoleculesOfOrder[RootNr];
    4551 //      *out << Verbose(1) << "Number of resulting molecules for Order " << (int)Walker->GetTrueFather()->AdaptiveOrder << " is: " << NumMoleculesOfOrder[RootNr] << "." << endl;
    4552       RootStack.push_back(RootKeyNr); // put back on stack
    4553       RootNr++;
    4554 
    4555       // free Order-dependent entries of UniqueFragments structure for next loop cycle
    4556       Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount");
    4557       for (int i=Order;i--;) {
    4558         delete(FragmentSearch.BondsPerSPList[2*i]);
    4559         delete(FragmentSearch.BondsPerSPList[2*i+1]);
    4560       }
    4561       Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList");
    4562     }
    4563   }
    4564   *out << Verbose(0) << "==============================================================================================================" << endl;
    4565   *out << Verbose(1) << "Total number of resulting molecules is: " << TotalNumMolecules << "." << endl;
    4566   *out << Verbose(0) << "==============================================================================================================" << endl;
    4567 
    4568   // cleanup FragmentSearch structure
    4569   Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList");
    4570   delete(FragmentSearch.FragmentSet);
    4571 
    4572   // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein)
    4573   // 5433222211111111
    4574   // 43221111
    4575   // 3211
    4576   // 21
    4577   // 1
    4578 
    4579   // Subsequently, we combine all into a single list (FragmentList)
    4580 
    4581   *out << Verbose(0) << "Combining the lists of all orders per order and finally into a single one." << endl;
    4582   if (FragmentList == NULL) {
    4583     FragmentList = new Graph;
    4584     counter = 0;
    4585   } else {
    4586     counter = FragmentList->size();
    4587   }
    4588   RootNr = 0;
    4589   while (!RootStack.empty()) {
    4590     RootKeyNr = RootStack.front();
    4591     RootStack.pop_front();
    4592     Walker = FindAtom(RootKeyNr);
    4593     NumLevels = 1 << (Walker->AdaptiveOrder - 1);
    4594     for(int i=0;i<NumLevels;i++) {
    4595       if (FragmentLowerOrdersList[RootNr][i] != NULL) {
    4596         InsertGraphIntoGraph(out, *FragmentList, (*FragmentLowerOrdersList[RootNr][i]), &counter);
    4597         delete(FragmentLowerOrdersList[RootNr][i]);
    4598       }
    4599     }
    4600     Free((void **)&FragmentLowerOrdersList[RootNr], "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]");
    4601     RootNr++;
    4602   }
    4603   Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList");
    4604   Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder");
    4605 
    4606   *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl;
     4523//                                                      // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules
     4524//                                                      //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl;
     4525//                                                      //NumMolecules = 0;
     4526//                                                      FragmentLowerOrdersList[RootNr][dest] = new Graph;
     4527//                                                      for(Graph::iterator runner = (*FragmentLowerOrdersList[RootNr][source]).begin();runner != (*FragmentLowerOrdersList[RootNr][source]).end(); runner++) {
     4528//                                                              for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) {
     4529//                                                                      Graph TempFragmentList;
     4530//                                                                      FragmentSearch.TEFactor = -(*runner).second.second;
     4531//                                                                      FragmentSearch.Leaflet = &TempFragmentList;                     // set to insertion graph
     4532//                                                                      FragmentSearch.Root = FindAtom(*sprinter);
     4533//                                                                      NumMoleculesOfOrder[RootNr] += PowerSetGenerator(out, SubOrder, FragmentSearch, (*runner).first);
     4534//                                                                      // insert new keysets FragmentList into FragmentLowerOrdersList[Walker->AdaptiveOrder-1][dest]
     4535//                                                                      *out << Verbose(1) << "Merging resulting key sets with those present in destination " << dest << "." << endl;
     4536//                                                                      InsertGraphIntoGraph(out, *FragmentLowerOrdersList[RootNr][dest], TempFragmentList, &NumMolecules);
     4537//                                                              }
     4538//                                                      }
     4539//                                                      *out << Verbose(1) << "Number of resulting molecules for SubOrder " << SubOrder << " is: " << NumMolecules << "." << endl;
     4540//                                              }
     4541//                                      }
     4542//                              }
     4543                        } else {
     4544                                Walker->GetTrueFather()->MaxOrder = true;
     4545//                              *out << Verbose(1) << "Hence, we don't dive into SubOrders ... " << endl;
     4546                        }
     4547                        // now, we have completely filled each cell of FragmentLowerOrdersList[] for the current Walker->AdaptiveOrder
     4548                        //NumMoleculesOfOrder[Walker->AdaptiveOrder-1] = NumMolecules;
     4549                        TotalNumMolecules += NumMoleculesOfOrder[RootNr];
     4550//                      *out << Verbose(1) << "Number of resulting molecules for Order " << (int)Walker->GetTrueFather()->AdaptiveOrder << " is: " << NumMoleculesOfOrder[RootNr] << "." << endl;
     4551                        RootStack.push_back(RootKeyNr); // put back on stack
     4552                        RootNr++;
     4553
     4554                        // free Order-dependent entries of UniqueFragments structure for next loop cycle
     4555                        Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount");
     4556                        for (int i=Order;i--;) {
     4557                                delete(FragmentSearch.BondsPerSPList[2*i]);
     4558                                delete(FragmentSearch.BondsPerSPList[2*i+1]);
     4559                        }
     4560                        Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList");
     4561                }
     4562        }
     4563        *out << Verbose(0) << "==============================================================================================================" << endl;
     4564        *out << Verbose(1) << "Total number of resulting molecules is: " << TotalNumMolecules << "." << endl;
     4565        *out << Verbose(0) << "==============================================================================================================" << endl;
     4566
     4567        // cleanup FragmentSearch structure
     4568        Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList");
     4569        delete(FragmentSearch.FragmentSet);
     4570
     4571        // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein)
     4572        // 5433222211111111
     4573        // 43221111
     4574        // 3211
     4575        // 21
     4576        // 1
     4577
     4578        // Subsequently, we combine all into a single list (FragmentList)
     4579
     4580        *out << Verbose(0) << "Combining the lists of all orders per order and finally into a single one." << endl;
     4581        if (FragmentList == NULL) {
     4582                FragmentList = new Graph;
     4583                counter = 0;
     4584        } else {
     4585                counter = FragmentList->size();
     4586        }
     4587        RootNr = 0;
     4588        while (!RootStack.empty()) {
     4589                RootKeyNr = RootStack.front();
     4590                RootStack.pop_front();
     4591                Walker = FindAtom(RootKeyNr);
     4592                NumLevels = 1 << (Walker->AdaptiveOrder - 1);
     4593                for(int i=0;i<NumLevels;i++) {
     4594                        if (FragmentLowerOrdersList[RootNr][i] != NULL) {
     4595                                InsertGraphIntoGraph(out, *FragmentList, (*FragmentLowerOrdersList[RootNr][i]), &counter);
     4596                                delete(FragmentLowerOrdersList[RootNr][i]);
     4597                        }
     4598                }
     4599                Free((void **)&FragmentLowerOrdersList[RootNr], "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]");
     4600                RootNr++;
     4601        }
     4602        Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList");
     4603        Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder");
     4604
     4605        *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl;
    46074606};
    46084607
     
    46144613inline int CompareDoubles (const void * a, const void * b)
    46154614{
    4616   if (*(double *)a > *(double *)b)
    4617     return -1;
    4618   else if (*(double *)a < *(double *)b)
    4619     return 1;
    4620   else
    4621     return 0;
     4615        if (*(double *)a > *(double *)b)
     4616                return -1;
     4617        else if (*(double *)a < *(double *)b)
     4618                return 1;
     4619        else
     4620                return 0;
    46224621};
    46234622
     
    46304629int * molecule::IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold)
    46314630{
    4632   int flag;
    4633   double *Distances = NULL, *OtherDistances = NULL;
    4634   Vector CenterOfGravity, OtherCenterOfGravity;
    4635   size_t *PermMap = NULL, *OtherPermMap = NULL;
    4636   int *PermutationMap = NULL;
    4637   atom *Walker = NULL;
    4638   bool result = true; // status of comparison
    4639 
    4640   *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl;
    4641   /// first count both their atoms and elements and update lists thereby ...
    4642   //*out << Verbose(0) << "Counting atoms, updating list" << endl;
    4643   CountAtoms(out);
    4644   OtherMolecule->CountAtoms(out);
    4645   CountElements();
    4646   OtherMolecule->CountElements();
    4647 
    4648   /// ... and compare:
    4649   /// -# AtomCount
    4650   if (result) {
    4651     if (AtomCount != OtherMolecule->AtomCount) {
    4652       *out << Verbose(4) << "AtomCounts don't match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl;
    4653       result = false;
    4654     } else *out << Verbose(4) << "AtomCounts match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl;
    4655   }
    4656   /// -# ElementCount
    4657   if (result) {
    4658     if (ElementCount != OtherMolecule->ElementCount) {
    4659       *out << Verbose(4) << "ElementCount don't match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;
    4660       result = false;
    4661     } else *out << Verbose(4) << "ElementCount match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;
    4662   }
    4663   /// -# ElementsInMolecule
    4664   if (result) {
    4665     for (flag=MAX_ELEMENTS;flag--;) {
    4666       //*out << Verbose(5) << "Element " <<  flag << ": " << ElementsInMolecule[flag] << " <-> " << OtherMolecule->ElementsInMolecule[flag] << "." << endl;
    4667       if (ElementsInMolecule[flag] != OtherMolecule->ElementsInMolecule[flag])
    4668         break;
    4669     }
    4670     if (flag < MAX_ELEMENTS) {
    4671       *out << Verbose(4) << "ElementsInMolecule don't match." << endl;
    4672       result = false;
    4673     } else *out << Verbose(4) << "ElementsInMolecule match." << endl;
    4674   }
    4675   /// then determine and compare center of gravity for each molecule ...
    4676   if (result) {
    4677     *out << Verbose(5) << "Calculating Centers of Gravity" << endl;
    4678     DetermineCenter(CenterOfGravity);
    4679     OtherMolecule->DetermineCenter(OtherCenterOfGravity);
    4680     *out << Verbose(5) << "Center of Gravity: ";
    4681     CenterOfGravity.Output(out);
    4682     *out << endl << Verbose(5) << "Other Center of Gravity: ";
    4683     OtherCenterOfGravity.Output(out);
    4684     *out << endl;
    4685     if (CenterOfGravity.Distance(&OtherCenterOfGravity) > threshold) {
    4686       *out << Verbose(4) << "Centers of gravity don't match." << endl;
    4687       result = false;
    4688     }
    4689   }
    4690 
    4691   /// ... then make a list with the euclidian distance to this center for each atom of both molecules
    4692   if (result) {
    4693     *out << Verbose(5) << "Calculating distances" << endl;
    4694     Distances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: Distances");
    4695     OtherDistances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: OtherDistances");
    4696     Walker = start;
    4697     while (Walker->next != end) {
    4698       Walker = Walker->next;
    4699       Distances[Walker->nr] = CenterOfGravity.Distance(&Walker->x);
    4700     }
    4701     Walker = OtherMolecule->start;
    4702     while (Walker->next != OtherMolecule->end) {
    4703       Walker = Walker->next;
    4704       OtherDistances[Walker->nr] = OtherCenterOfGravity.Distance(&Walker->x);
    4705     }
    4706 
    4707     /// ... sort each list (using heapsort (o(N log N)) from GSL)
    4708     *out << Verbose(5) << "Sorting distances" << endl;
    4709     PermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermMap");
    4710     OtherPermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *OtherPermMap");
    4711     gsl_heapsort_index (PermMap, Distances, AtomCount, sizeof(double), CompareDoubles);
    4712     gsl_heapsort_index (OtherPermMap, OtherDistances, AtomCount, sizeof(double), CompareDoubles);
    4713     PermutationMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermutationMap");
    4714     *out << Verbose(5) << "Combining Permutation Maps" << endl;
    4715     for(int i=AtomCount;i--;)
    4716       PermutationMap[PermMap[i]] = (int) OtherPermMap[i];
    4717 
    4718     /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all
    4719     *out << Verbose(4) << "Comparing distances" << endl;
    4720     flag = 0;
    4721     for (int i=0;i<AtomCount;i++) {
    4722       *out << Verbose(5) << "Distances: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " <<  threshold << endl;
    4723       if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) > threshold)
    4724         flag = 1;
    4725     }
    4726     Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap");
    4727     Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap");
    4728 
    4729     /// free memory
    4730     Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances");
    4731     Free((void **)&OtherDistances, "molecule::IsEqualToWithinThreshold: OtherDistances");
    4732     if (flag) { // if not equal
    4733       Free((void **)&PermutationMap, "molecule::IsEqualToWithinThreshold: *PermutationMap");
    4734       result = false;
    4735     }
    4736   }
    4737   /// return pointer to map if all distances were below \a threshold
    4738   *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl;
    4739   if (result) {
    4740     *out << Verbose(3) << "Result: Equal." << endl;
    4741     return PermutationMap;
    4742   } else {
    4743     *out << Verbose(3) << "Result: Not equal." << endl;
    4744     return NULL;
    4745   }
     4631        int flag;
     4632        double *Distances = NULL, *OtherDistances = NULL;
     4633        Vector CenterOfGravity, OtherCenterOfGravity;
     4634        size_t *PermMap = NULL, *OtherPermMap = NULL;
     4635        int *PermutationMap = NULL;
     4636        atom *Walker = NULL;
     4637        bool result = true; // status of comparison
     4638
     4639        *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl;
     4640        /// first count both their atoms and elements and update lists thereby ...
     4641        //*out << Verbose(0) << "Counting atoms, updating list" << endl;
     4642        CountAtoms(out);
     4643        OtherMolecule->CountAtoms(out);
     4644        CountElements();
     4645        OtherMolecule->CountElements();
     4646
     4647        /// ... and compare:
     4648        /// -# AtomCount
     4649        if (result) {
     4650                if (AtomCount != OtherMolecule->AtomCount) {
     4651                        *out << Verbose(4) << "AtomCounts don't match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl;
     4652                        result = false;
     4653                } else *out << Verbose(4) << "AtomCounts match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl;
     4654        }
     4655        /// -# ElementCount
     4656        if (result) {
     4657                if (ElementCount != OtherMolecule->ElementCount) {
     4658                        *out << Verbose(4) << "ElementCount don't match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;
     4659                        result = false;
     4660                } else *out << Verbose(4) << "ElementCount match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;
     4661        }
     4662        /// -# ElementsInMolecule
     4663        if (result) {
     4664                for (flag=MAX_ELEMENTS;flag--;) {
     4665                        //*out << Verbose(5) << "Element " <<   flag << ": " << ElementsInMolecule[flag] << " <-> " << OtherMolecule->ElementsInMolecule[flag] << "." << endl;
     4666                        if (ElementsInMolecule[flag] != OtherMolecule->ElementsInMolecule[flag])
     4667                                break;
     4668                }
     4669                if (flag < MAX_ELEMENTS) {
     4670                        *out << Verbose(4) << "ElementsInMolecule don't match." << endl;
     4671                        result = false;
     4672                } else *out << Verbose(4) << "ElementsInMolecule match." << endl;
     4673        }
     4674        /// then determine and compare center of gravity for each molecule ...
     4675        if (result) {
     4676                *out << Verbose(5) << "Calculating Centers of Gravity" << endl;
     4677                DetermineCenter(CenterOfGravity);
     4678                OtherMolecule->DetermineCenter(OtherCenterOfGravity);
     4679                *out << Verbose(5) << "Center of Gravity: ";
     4680                CenterOfGravity.Output(out);
     4681                *out << endl << Verbose(5) << "Other Center of Gravity: ";
     4682                OtherCenterOfGravity.Output(out);
     4683                *out << endl;
     4684                if (CenterOfGravity.DistanceSquared(&OtherCenterOfGravity) > threshold*threshold) {
     4685                        *out << Verbose(4) << "Centers of gravity don't match." << endl;
     4686                        result = false;
     4687                }
     4688        }
     4689
     4690        /// ... then make a list with the euclidian distance to this center for each atom of both molecules
     4691        if (result) {
     4692                *out << Verbose(5) << "Calculating distances" << endl;
     4693                Distances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: Distances");
     4694                OtherDistances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: OtherDistances");
     4695                Walker = start;
     4696                while (Walker->next != end) {
     4697                        Walker = Walker->next;
     4698                        Distances[Walker->nr] = CenterOfGravity.DistanceSquared(&Walker->x);
     4699                }
     4700                Walker = OtherMolecule->start;
     4701                while (Walker->next != OtherMolecule->end) {
     4702                        Walker = Walker->next;
     4703                        OtherDistances[Walker->nr] = OtherCenterOfGravity.DistanceSquared(&Walker->x);
     4704                }
     4705
     4706                /// ... sort each list (using heapsort (o(N log N)) from GSL)
     4707                *out << Verbose(5) << "Sorting distances" << endl;
     4708                PermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermMap");
     4709                OtherPermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *OtherPermMap");
     4710                gsl_heapsort_index (PermMap, Distances, AtomCount, sizeof(double), CompareDoubles);
     4711                gsl_heapsort_index (OtherPermMap, OtherDistances, AtomCount, sizeof(double), CompareDoubles);
     4712                PermutationMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermutationMap");
     4713                *out << Verbose(5) << "Combining Permutation Maps" << endl;
     4714                for(int i=AtomCount;i--;)
     4715                        PermutationMap[PermMap[i]] = (int) OtherPermMap[i];
     4716
     4717                /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all
     4718                *out << Verbose(4) << "Comparing distances" << endl;
     4719                flag = 0;
     4720                for (int i=0;i<AtomCount;i++) {
     4721                        *out << Verbose(5) << "Distances squared: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " <<      threshold << endl;
     4722                        if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) > threshold*threshold)
     4723                                flag = 1;
     4724                }
     4725                Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap");
     4726                Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap");
     4727
     4728                /// free memory
     4729                Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances");
     4730                Free((void **)&OtherDistances, "molecule::IsEqualToWithinThreshold: OtherDistances");
     4731                if (flag) { // if not equal
     4732                        Free((void **)&PermutationMap, "molecule::IsEqualToWithinThreshold: *PermutationMap");
     4733                        result = false;
     4734                }
     4735        }
     4736        /// return pointer to map if all distances were below \a threshold
     4737        *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl;
     4738        if (result) {
     4739                *out << Verbose(3) << "Result: Equal." << endl;
     4740                return PermutationMap;
     4741        } else {
     4742                *out << Verbose(3) << "Result: Not equal." << endl;
     4743                return NULL;
     4744        }
    47464745};
    47474746
     
    47554754int * molecule::GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule)
    47564755{
    4757   atom *Walker = NULL, *OtherWalker = NULL;
    4758   *out << Verbose(3) << "Begin of GetFatherAtomicMap." << endl;
    4759   int *AtomicMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::GetAtomicMap: *AtomicMap");  //Calloc
    4760   for (int i=AtomCount;i--;)
    4761     AtomicMap[i] = -1;
    4762   if (OtherMolecule == this) {  // same molecule
    4763     for (int i=AtomCount;i--;) // no need as -1 means already that there is trivial correspondence
    4764       AtomicMap[i] = i;
    4765     *out << Verbose(4) << "Map is trivial." << endl;
    4766   } else {
    4767     *out << Verbose(4) << "Map is ";
    4768     Walker = start;
    4769     while (Walker->next != end) {
    4770       Walker = Walker->next;
    4771       if (Walker->father == NULL) {
    4772         AtomicMap[Walker->nr] = -2;
    4773       } else {
    4774         OtherWalker = OtherMolecule->start;
    4775         while (OtherWalker->next != OtherMolecule->end) {
    4776           OtherWalker = OtherWalker->next;
    4777       //for (int i=0;i<AtomCount;i++) { // search atom
    4778         //for (int j=0;j<OtherMolecule->AtomCount;j++) {
    4779           //*out << Verbose(4) << "Comparing father " << Walker->father << " with the other one " << OtherWalker->father << "." << endl;
    4780           if (Walker->father == OtherWalker)
    4781             AtomicMap[Walker->nr] = OtherWalker->nr;
    4782         }
    4783       }
    4784       *out << AtomicMap[Walker->nr] << "\t";
    4785     }
    4786     *out << endl;
    4787   }
    4788   *out << Verbose(3) << "End of GetFatherAtomicMap." << endl;
    4789   return AtomicMap;
     4756        atom *Walker = NULL, *OtherWalker = NULL;
     4757        *out << Verbose(3) << "Begin of GetFatherAtomicMap." << endl;
     4758        int *AtomicMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::GetAtomicMap: *AtomicMap");   //Calloc
     4759        for (int i=AtomCount;i--;)
     4760                AtomicMap[i] = -1;
     4761        if (OtherMolecule == this) {    // same molecule
     4762                for (int i=AtomCount;i--;) // no need as -1 means already that there is trivial correspondence
     4763                        AtomicMap[i] = i;
     4764                *out << Verbose(4) << "Map is trivial." << endl;
     4765        } else {
     4766                *out << Verbose(4) << "Map is ";
     4767                Walker = start;
     4768                while (Walker->next != end) {
     4769                        Walker = Walker->next;
     4770                        if (Walker->father == NULL) {
     4771                                AtomicMap[Walker->nr] = -2;
     4772                        } else {
     4773                                OtherWalker = OtherMolecule->start;
     4774                                while (OtherWalker->next != OtherMolecule->end) {
     4775                                        OtherWalker = OtherWalker->next;
     4776                        //for (int i=0;i<AtomCount;i++) { // search atom
     4777                                //for (int j=0;j<OtherMolecule->AtomCount;j++) {
     4778                                        //*out << Verbose(4) << "Comparing father " << Walker->father << " with the other one " << OtherWalker->father << "." << endl;
     4779                                        if (Walker->father == OtherWalker)
     4780                                                AtomicMap[Walker->nr] = OtherWalker->nr;
     4781                                }
     4782                        }
     4783                        *out << AtomicMap[Walker->nr] << "\t";
     4784                }
     4785                *out << endl;
     4786        }
     4787        *out << Verbose(3) << "End of GetFatherAtomicMap." << endl;
     4788        return AtomicMap;
    47904789};
    47914790
     
    48014800bool molecule::OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output)
    48024801{
    4803   double temperature;
    4804   atom *Walker = NULL;
    4805   // test stream
    4806   if (output == NULL)
    4807     return false;
    4808   else
    4809     *output << "# Step Temperature [K] Temperature [a.u.]" << endl;
    4810   for (int step=startstep;step < endstep; step++) { // loop over all time steps
    4811     temperature = 0.;
    4812     Walker = start;
    4813     while (Walker->next != end) {
    4814       Walker = Walker->next;
    4815       for (int i=NDIM;i--;)
    4816         temperature += Walker->type->mass * Trajectories[Walker].U.at(step).x[i]* Trajectories[Walker].U.at(step).x[i];
    4817     }
    4818     *output << step << "\t" << temperature*AtomicEnergyToKelvin << "\t" << temperature << endl;
    4819   }
    4820   return true;
    4821 };
     4802        double temperature;
     4803        atom *Walker = NULL;
     4804        // test stream
     4805        if (output == NULL)
     4806                return false;
     4807        else
     4808                *output << "# Step Temperature [K] Temperature [a.u.]" << endl;
     4809        for (int step=startstep;step < endstep; step++) { // loop over all time steps
     4810                temperature = 0.;
     4811                Walker = start;
     4812                while (Walker->next != end) {
     4813                        Walker = Walker->next;
     4814                        for (int i=NDIM;i--;)
     4815                                temperature += Walker->type->mass * Trajectories[Walker].U.at(step).x[i]* Trajectories[Walker].U.at(step).x[i];
     4816                }
     4817                *output << step << "\t" << temperature*AtomicEnergyToKelvin << "\t" << temperature << endl;
     4818        }
     4819        return true;
     4820};
  • src/molecules.hpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    6060#define LineMap map < int, class BoundaryLineSet * >
    6161#define LinePair pair < int, class BoundaryLineSet * >
    62 #define LineTestPair pair < LinePair::iterator, bool >
     62#define LineTestPair pair < LineMap::iterator, bool >
    6363
    6464#define TriangleMap map < int, class BoundaryTriangleSet * >
     
    7373struct KeyCompare
    7474{
    75   bool operator() (const KeySet SubgraphA, const KeySet SubgraphB) const;
     75        bool operator() (const KeySet SubgraphA, const KeySet SubgraphB) const;
    7676};
    7777
    7878struct Trajectory
    7979{
    80   vector<Vector> R;  //!< position vector
    81   vector<Vector> U;  //!< velocity vector
    82   vector<Vector> F;  //!< last force vector
    83   atom *ptr;        //!< pointer to atom whose trajectory we contain
    84 };
    85 
    86 //bool operator < (KeySet SubgraphA, KeySet SubgraphB);  //note: this declaration is important, otherwise normal < is used (producing wrong order)
     80        vector<Vector> R;       //!< position vector
     81        vector<Vector> U;       //!< velocity vector
     82        vector<Vector> F;       //!< last force vector
     83        atom *ptr;                              //!< pointer to atom whose trajectory we contain
     84};
     85
     86//bool operator < (KeySet SubgraphA, KeySet SubgraphB);  //note: this declaration is important, otherwise normal < is used (producing wrong order)
    8787inline void InsertFragmentIntoGraph(ofstream *out, struct UniqueFragments *Fragment); // Insert a KeySet into a Graph
    88 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter);  // Insert all KeySet's in a Graph into another Graph
     88inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter);    // Insert all KeySet's in a Graph into another Graph
    8989int CompareDoubles (const void * a, const void * b);
    9090
     
    9494
    9595// some algebraic matrix stuff
    96 #define RDET3(a) ((a)[0]*(a)[4]*(a)[8] + (a)[3]*(a)[7]*(a)[2] + (a)[6]*(a)[1]*(a)[5] - (a)[2]*(a)[4]*(a)[6] - (a)[5]*(a)[7]*(a)[0] - (a)[8]*(a)[1]*(a)[3])  //!< hard-coded determinant of a 3x3 matrix
    97 #define RDET2(a0,a1,a2,a3) ((a0)*(a3)-(a1)*(a2))                      //!< hard-coded determinant of a 2x2 matrix
     96#define RDET3(a) ((a)[0]*(a)[4]*(a)[8] + (a)[3]*(a)[7]*(a)[2] + (a)[6]*(a)[1]*(a)[5] - (a)[2]*(a)[4]*(a)[6] - (a)[5]*(a)[7]*(a)[0] - (a)[8]*(a)[1]*(a)[3])      //!< hard-coded determinant of a 3x3 matrix
     97#define RDET2(a0,a1,a2,a3) ((a0)*(a3)-(a1)*(a2))                                                                                        //!< hard-coded determinant of a 2x2 matrix
    9898
    9999
     
    101101 */
    102102struct LSQ_params {
    103   Vector **vectors;
    104   int num;
     103        Vector **vectors;
     104        int num;
    105105};
    106106
     
    110110 */
    111111struct lsq_params {
    112   gsl_vector *x;
    113   const molecule *mol;
    114   element *type;
    115 };
    116 
    117 
     112        gsl_vector *x;
     113        const molecule *mol;
     114        element *type;
     115};
    118116
    119117/** Single atom.
     
    121119 */
    122120class atom {
    123   public:
    124     Vector x;      //!< coordinate array of atom, giving position within cell
    125     Vector v;      //!< velocity array of atom
    126     element *type;  //!< pointing to element
    127     atom *previous; //!< previous atom in molecule list
    128     atom *next;    //!< next atom in molecule list
    129     atom *father;  //!< In many-body bond order fragmentations points to originating atom
    130     atom *Ancestor; //!< "Father" in Depth-First-Search
    131     char *Name;                 //!< unique name used during many-body bond-order fragmentation
    132     int FixedIon;  //!< config variable that states whether forces act on the ion or not
    133     int *sort;      //!< sort criteria
    134     int nr;        //!< continuous, unique number
    135     int GraphNr;      //!< unique number, given in DepthFirstSearchAnalysis()
    136     int *ComponentNr;//!< belongs to this nonseparable components, given in DepthFirstSearchAnalysis() (if more than one, then is SeparationVertex)
    137     int LowpointNr; //!< needed in DepthFirstSearchAnalysis() to detect nonseparable components, is the lowest possible number of an atom to reach via tree edges only followed by at most one back edge.
    138     bool SeparationVertex; //!< whether this atom separates off subsets of atoms or not, determined in DepthFirstSearchAnalysis()
    139     bool IsCyclic;        //!< whether atom belong to as cycle or not, determined in DepthFirstSearchAnalysis()
    140     unsigned char AdaptiveOrder;  //!< current present bond order at site (0 means "not set")
    141     bool MaxOrder;  //!< whether this atom as a root in fragmentation still creates more fragments on higher orders or not
    142 
    143   atom();
    144   ~atom();
    145 
    146   bool Output(int ElementNo, int AtomNo, ofstream *out) const;
    147   bool OutputXYZLine(ofstream *out) const;
    148   atom *GetTrueFather();
    149   bool Compare(atom &ptr);
    150 
    151   private:
     121        public:
     122                Vector x;                        //!< coordinate array of atom, giving position within cell
     123                Vector v;                        //!< velocity array of atom
     124                element *type;  //!< pointing to element
     125                atom *previous; //!< previous atom in molecule list
     126                atom *next;              //!< next atom in molecule list
     127                atom *father;    //!< In many-body bond order fragmentations points to originating atom
     128                atom *Ancestor; //!< "Father" in Depth-First-Search
     129                char *Name;                     //!< unique name used during many-body bond-order fragmentation
     130                int FixedIon;    //!< config variable that states whether forces act on the ion or not
     131                int *sort;                      //!< sort criteria
     132                int nr;                          //!< continuous, unique number
     133                int GraphNr;                    //!< unique number, given in DepthFirstSearchAnalysis()
     134                int *ComponentNr;//!< belongs to this nonseparable components, given in DepthFirstSearchAnalysis() (if more than one, then is SeparationVertex)
     135                int LowpointNr; //!< needed in DepthFirstSearchAnalysis() to detect nonseparable components, is the lowest possible number of an atom to reach via tree edges only followed by at most one back edge.
     136                bool SeparationVertex; //!< whether this atom separates off subsets of atoms or not, determined in DepthFirstSearchAnalysis()
     137                bool IsCyclic;                          //!< whether atom belong to as cycle or not, determined in DepthFirstSearchAnalysis()
     138                unsigned char AdaptiveOrder;    //!< current present bond order at site (0 means "not set")
     139                bool MaxOrder;  //!< whether this atom as a root in fragmentation still creates more fragments on higher orders or not
     140
     141        atom();
     142        ~atom();
     143
     144        bool Output(int ElementNo, int AtomNo, ofstream *out) const;
     145        bool OutputXYZLine(ofstream *out) const;
     146        atom *GetTrueFather();
     147        bool Compare(atom &ptr);
     148
     149        private:
    152150};
    153151
     
    160158 */
    161159class bond {
    162   public:
    163         atom *leftatom;         //!< first bond partner
    164         atom *rightatom;        //!< second bond partner
    165     bond *previous; //!< previous atom in molecule list
    166     bond *next;    //!< next atom in molecule list
    167         int HydrogenBond;       //!< Number of hydrogen atoms in the bond
    168         int BondDegree;         //!< single, double, triple, ... bond
    169     int nr;          //!< unique number in a molecule, updated by molecule::CreateAdjacencyList()
    170     bool Cyclic;      //!< flag whether bond is part of a cycle or not, given in DepthFirstSearchAnalysis()
    171     enum EdgeType Type;//!< whether this is a tree or back edge
    172 
    173   atom * GetOtherAtom(atom *Atom) const;
    174   bond * GetFirstBond();
    175   bond * GetLastBond();
    176 
    177   bool MarkUsed(enum Shading color);
    178   enum Shading IsUsed();
    179   void ResetUsed();
    180   bool Contains(const atom *ptr);
    181   bool Contains(const int nr);
    182 
    183   bond();
    184   bond(atom *left, atom *right);
    185   bond(atom *left, atom *right, int degree);
    186   bond(atom *left, atom *right, int degree, int number);
    187   ~bond();
    188 
    189   private:
    190     enum Shading Used;        //!< marker in depth-first search, DepthFirstSearchAnalysis()
     160        public:
     161                atom *leftatom;         //!< first bond partner
     162                atom *rightatom;        //!< second bond partner
     163                bond *previous; //!< previous atom in molecule list
     164                bond *next;              //!< next atom in molecule list
     165                int HydrogenBond;       //!< Number of hydrogen atoms in the bond
     166                int BondDegree;         //!< single, double, triple, ... bond
     167                int nr;                                  //!< unique number in a molecule, updated by molecule::CreateAdjacencyList()
     168                bool Cyclic;                    //!< flag whether bond is part of a cycle or not, given in DepthFirstSearchAnalysis()
     169                enum EdgeType Type;//!< whether this is a tree or back edge
     170
     171        atom * GetOtherAtom(atom *Atom) const;
     172        bond * GetFirstBond();
     173        bond * GetLastBond();
     174
     175        bool MarkUsed(enum Shading color);
     176        enum Shading IsUsed();
     177        void ResetUsed();
     178        bool Contains(const atom *ptr);
     179        bool Contains(const int nr);
     180
     181        bond();
     182        bond(atom *left, atom *right);
     183        bond(atom *left, atom *right, int degree);
     184        bond(atom *left, atom *right, int degree, int number);
     185        ~bond();
     186
     187        private:
     188                enum Shading Used;                              //!< marker in depth-first search, DepthFirstSearchAnalysis()
    191189};
    192190
     
    199197 */
    200198class molecule {
    201   public:
    202     double cell_size[6];//!< cell size
    203     periodentafel *elemente; //!< periodic table with each element
    204     atom *start;        //!< start of atom list
    205     atom *end;          //!< end of atom list
    206     bond *first;        //!< start of bond list
    207     bond *last;        //!< end of bond list
    208     bond ***ListOfBondsPerAtom; //!< pointer list for each atom and each bond it has
    209     map<atom *, struct Trajectory> Trajectories; //!< contains old trajectory points
    210     int MDSteps;        //!< The number of MD steps in Trajectories
    211     int *NumberOfBondsPerAtom;  //!< Number of Bonds each atom has
    212     int AtomCount;                                      //!< number of atoms, brought up-to-date by CountAtoms()
    213     int BondCount;                                      //!< number of atoms, brought up-to-date by CountBonds()
    214     int ElementCount;      //!< how many unique elements are therein
    215     int ElementsInMolecule[MAX_ELEMENTS]; //!< list whether element (sorted by atomic number) is alread present or not
    216     int NoNonHydrogen;  //!< number of non-hydrogen atoms in molecule
    217     int NoNonBonds;    //!< number of non-hydrogen bonds in molecule
    218     int NoCyclicBonds;  //!< number of cyclic bonds in molecule, by DepthFirstSearchAnalysis()
    219     double BondDistance;  //!< typical bond distance used in CreateAdjacencyList() and furtheron
    220 
    221   molecule(periodentafel *teil);
    222   ~molecule();
    223 
    224   /// remove atoms from molecule.
    225   bool AddAtom(atom *pointer);
    226   bool RemoveAtom(atom *pointer);
    227   bool CleanupMolecule();
    228 
    229   /// Add/remove atoms to/from molecule.
    230   atom * AddCopyAtom(atom *pointer);
    231   bool AddXYZFile(string filename);
    232   bool AddHydrogenReplacementAtom(ofstream *out, bond *Bond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem);
    233   bond * AddBond(atom *first, atom *second, int degree);
    234   bool RemoveBond(bond *pointer);
    235   bool RemoveBonds(atom *BondPartner);
    236 
    237   /// Find atoms.
    238   atom * FindAtom(int Nr) const;
    239   atom * AskAtom(string text);
    240 
    241   /// Count and change present atoms' coordination.
    242   void CountAtoms(ofstream *out);
    243   void CountElements();
    244   void CalculateOrbitals(class config &configuration);
    245   bool CenterInBox(ofstream *out, Vector *BoxLengths);
    246   void CenterEdge(ofstream *out, Vector *max);
    247   void CenterOrigin(ofstream *out, Vector *max);
    248   void CenterGravity(ofstream *out, Vector *max);
    249   void Translate(const Vector *x);
    250   void Mirror(const Vector *x);
    251   void Align(Vector *n);
    252   void Scale(double **factor);
    253   void DetermineCenter(Vector &center);
    254   Vector * DetermineCenterOfGravity(ofstream *out);
    255   Vector * DetermineCenterOfAll(ofstream *out);
    256   void SetBoxDimension(Vector *dim);
    257   double * ReturnFullMatrixforSymmetric(double *cell_size);
    258   void ScanForPeriodicCorrection(ofstream *out);
     199        public:
     200                double cell_size[6];//!< cell size
     201                periodentafel *elemente; //!< periodic table with each element
     202                atom *start;                            //!< start of atom list
     203                atom *end;                                      //!< end of atom list
     204                bond *first;                            //!< start of bond list
     205                bond *last;                              //!< end of bond list
     206                bond ***ListOfBondsPerAtom; //!< pointer list for each atom and each bond it has
     207                map<atom *, struct Trajectory> Trajectories; //!< contains old trajectory points
     208                int MDSteps;                            //!< The number of MD steps in Trajectories
     209                int *NumberOfBondsPerAtom;      //!< Number of Bonds each atom has
     210                int AtomCount;                                  //!< number of atoms, brought up-to-date by CountAtoms()
     211                int BondCount;                                  //!< number of atoms, brought up-to-date by CountBonds()
     212                int ElementCount;                        //!< how many unique elements are therein
     213                int ElementsInMolecule[MAX_ELEMENTS]; //!< list whether element (sorted by atomic number) is alread present or not
     214                int NoNonHydrogen;      //!< number of non-hydrogen atoms in molecule
     215                int NoNonBonds;          //!< number of non-hydrogen bonds in molecule
     216                int NoCyclicBonds;      //!< number of cyclic bonds in molecule, by DepthFirstSearchAnalysis()
     217                double BondDistance;    //!< typical bond distance used in CreateAdjacencyList() and furtheron
     218
     219        molecule(periodentafel *teil);
     220        ~molecule();
     221
     222        /// remove atoms from molecule.
     223        bool AddAtom(atom *pointer);
     224        bool RemoveAtom(atom *pointer);
     225        bool CleanupMolecule();
     226
     227        /// Add/remove atoms to/from molecule.
     228        atom * AddCopyAtom(atom *pointer);
     229        bool AddXYZFile(string filename);
     230        bool AddHydrogenReplacementAtom(ofstream *out, bond *Bond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem);
     231        bond * AddBond(atom *first, atom *second, int degree);
     232        bool RemoveBond(bond *pointer);
     233        bool RemoveBonds(atom *BondPartner);
     234
     235        /// Find atoms.
     236        atom * FindAtom(int Nr) const;
     237        atom * AskAtom(string text);
     238
     239        /// Count and change present atoms' coordination.
     240        void CountAtoms(ofstream *out);
     241        void CountElements();
     242        void CalculateOrbitals(class config &configuration);
     243        bool CenterInBox(ofstream *out, Vector *BoxLengths);
     244        void CenterEdge(ofstream *out, Vector *max);
     245        void CenterOrigin(ofstream *out, Vector *max);
     246        void CenterGravity(ofstream *out, Vector *max);
     247        void Translate(const Vector *x);
     248        void Mirror(const Vector *x);
     249        void Align(Vector *n);
     250        void Scale(double **factor);
     251        void DetermineCenter(Vector &center);
     252        Vector * DetermineCenterOfGravity(ofstream *out);
     253        Vector * DetermineCenterOfAll(ofstream *out);
     254        void SetBoxDimension(Vector *dim);
     255        double * ReturnFullMatrixforSymmetric(double *cell_size);
     256        void ScanForPeriodicCorrection(ofstream *out);
    259257        void PrincipalAxisSystem(ofstream *out, bool DoRotate);
    260258        double VolumeOfConvexEnvelope(ofstream *out, bool IsAngstroem);
    261259        bool VerletForceIntegration(char *file, double delta_t, bool IsAngstroem);
    262260
    263   bool CheckBounds(const Vector *x) const;
    264   void GetAlignvector(struct lsq_params * par) const;
    265 
    266   /// Initialising routines in fragmentation
    267   void CreateAdjacencyList2(ofstream *out, ifstream *output);
    268   void CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem);
    269   void CreateListOfBondsPerAtom(ofstream *out);
    270 
    271   // Graph analysis
    272   MoleculeLeafClass * DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack);
    273   void CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> *BackEdgeStack, int *&MinimumRingSize);
    274   bool PickLocalBackEdges(ofstream *out, atom **ListOfLocalAtoms, class StackClass<bond *> *&ReferenceStack, class StackClass<bond *> *&LocalStack);
    275   bond * FindNextUnused(atom *vertex);
    276   void SetNextComponentNumber(atom *vertex, int nr);
    277   void InitComponentNumbers();
    278   void OutputComponentNumber(ofstream *out, atom *vertex);
    279   void ResetAllBondsToUnused();
    280   void ResetAllAtomNumbers();
    281   int CountCyclicBonds(ofstream *out);
    282   bool CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment);
    283   string GetColor(enum Shading color);
    284 
    285   molecule *CopyMolecule();
    286 
    287   /// Fragment molecule by two different approaches:
    288   int FragmentMolecule(ofstream *out, int Order, config *configuration);
    289   bool CheckOrderAtSite(ofstream *out, bool *AtomMask, Graph *GlobalKeySetList, int Order, int *MinimumRingSize, char *path = NULL);
    290   bool StoreAdjacencyToFile(ofstream *out, char *path);
    291   bool CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms);
    292   bool ParseOrderAtSiteFromFile(ofstream *out, char *path);
    293   bool StoreOrderAtSiteFile(ofstream *out, char *path);
    294   bool ParseKeySetFile(ofstream *out, char *filename, Graph *&FragmentList);
    295   bool StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path);
    296   bool StoreForcesFile(ofstream *out, MoleculeListClass *BondFragments, char *path, int *SortIndex);
    297   bool CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex);
    298   bool ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet);
    299   void BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem);
    300   /// -# BOSSANOVA
    301   void FragmentBOSSANOVA(ofstream *out, Graph *&FragmentList, KeyStack &RootStack, int *MinimumRingSize);
     261        bool CheckBounds(const Vector *x) const;
     262        void GetAlignvector(struct lsq_params * par) const;
     263
     264        /// Initialising routines in fragmentation
     265        void CreateAdjacencyList2(ofstream *out, ifstream *output);
     266        void CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem);
     267        void CreateListOfBondsPerAtom(ofstream *out);
     268
     269        // Graph analysis
     270        MoleculeLeafClass * DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack);
     271        void CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> *BackEdgeStack, int *&MinimumRingSize);
     272        bool PickLocalBackEdges(ofstream *out, atom **ListOfLocalAtoms, class StackClass<bond *> *&ReferenceStack, class StackClass<bond *> *&LocalStack);
     273        bond * FindNextUnused(atom *vertex);
     274        void SetNextComponentNumber(atom *vertex, int nr);
     275        void InitComponentNumbers();
     276        void OutputComponentNumber(ofstream *out, atom *vertex);
     277        void ResetAllBondsToUnused();
     278        void ResetAllAtomNumbers();
     279        int CountCyclicBonds(ofstream *out);
     280        bool CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment);
     281        string GetColor(enum Shading color);
     282
     283        molecule *CopyMolecule();
     284
     285        /// Fragment molecule by two different approaches:
     286        int FragmentMolecule(ofstream *out, int Order, config *configuration);
     287        bool CheckOrderAtSite(ofstream *out, bool *AtomMask, Graph *GlobalKeySetList, int Order, int *MinimumRingSize, char *path = NULL);
     288        bool StoreAdjacencyToFile(ofstream *out, char *path);
     289        bool CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms);
     290        bool ParseOrderAtSiteFromFile(ofstream *out, char *path);
     291        bool StoreOrderAtSiteFile(ofstream *out, char *path);
     292        bool ParseKeySetFile(ofstream *out, char *filename, Graph *&FragmentList);
     293        bool StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path);
     294        bool StoreForcesFile(ofstream *out, MoleculeListClass *BondFragments, char *path, int *SortIndex);
     295        bool CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex);
     296        bool ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet);
     297        void BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem);
     298        /// -# BOSSANOVA
     299        void FragmentBOSSANOVA(ofstream *out, Graph *&FragmentList, KeyStack &RootStack, int *MinimumRingSize);
    302300        int PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet);
    303   bool BuildInducedSubgraph(ofstream *out, const molecule *Father);
    304   molecule * StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem);
    305   void SPFragmentGenerator(ofstream *out, struct UniqueFragments *FragmentSearch, int RootDistance, bond **BondsSet, int SetDimension, int SubOrder);
    306   int LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList);
    307   int GuesstimateFragmentCount(ofstream *out, int order);
    308 
    309   // Recognize doubly appearing molecules in a list of them
    310   int * IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold);
    311   int * GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule);
    312 
    313   // Output routines.
    314   bool Output(ofstream *out);
    315   bool OutputTrajectories(ofstream *out);
    316   void OutputListOfBonds(ofstream *out) const;
    317   bool OutputXYZ(ofstream *out) const;
    318   bool OutputTrajectoriesXYZ(ofstream *out);
    319   bool Checkout(ofstream *out) const;
    320   bool OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output);
    321 
    322   private:
    323   int last_atom;      //!< number given to last atom
     301        bool BuildInducedSubgraph(ofstream *out, const molecule *Father);
     302        molecule * StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem);
     303        void SPFragmentGenerator(ofstream *out, struct UniqueFragments *FragmentSearch, int RootDistance, bond **BondsSet, int SetDimension, int SubOrder);
     304        int LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList);
     305        int GuesstimateFragmentCount(ofstream *out, int order);
     306
     307        // Recognize doubly appearing molecules in a list of them
     308        int * IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold);
     309        int * GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule);
     310
     311        // Output routines.
     312        bool Output(ofstream *out);
     313        bool OutputTrajectories(ofstream *out);
     314        void OutputListOfBonds(ofstream *out) const;
     315        bool OutputXYZ(ofstream *out) const;
     316        bool OutputTrajectoriesXYZ(ofstream *out);
     317        bool Checkout(ofstream *out) const;
     318        bool OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output);
     319
     320        private:
     321        int last_atom;                  //!< number given to last atom
    324322};
    325323
     
    327325 */
    328326class MoleculeListClass {
    329   public:
    330     molecule **ListOfMolecules;  //!< pointer list of fragment molecules to check for equality
    331     int NumberOfMolecules;        //!< Number of entries in \a **FragmentList and of to be returned one.
    332     int NumberOfTopAtoms;        //!< Number of atoms in the molecule from which all fragments originate
    333 
    334   MoleculeListClass();
    335   MoleculeListClass(int Num, int NumAtoms);
    336   ~MoleculeListClass();
    337 
    338   /// Output configs.
    339   bool AddHydrogenCorrection(ofstream *out, char *path);
    340   bool StoreForcesFile(ofstream *out, char *path, int *SortIndex);
    341   bool OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex);
    342   void Output(ofstream *out);
    343 
    344   private:
     327        public:
     328                molecule **ListOfMolecules;      //!< pointer list of fragment molecules to check for equality
     329                int NumberOfMolecules;                          //!< Number of entries in \a **FragmentList and of to be returned one.
     330                int NumberOfTopAtoms;                            //!< Number of atoms in the molecule from which all fragments originate
     331
     332        MoleculeListClass();
     333        MoleculeListClass(int Num, int NumAtoms);
     334        ~MoleculeListClass();
     335
     336        /// Output configs.
     337        bool AddHydrogenCorrection(ofstream *out, char *path);
     338        bool StoreForcesFile(ofstream *out, char *path, int *SortIndex);
     339        bool OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex);
     340        void Output(ofstream *out);
     341
     342        private:
    345343};
    346344
     
    350348 */
    351349class MoleculeLeafClass {
    352   public:
    353     molecule *Leaf;                  //!< molecule of this leaf
    354     //MoleculeLeafClass *UpLeaf;        //!< Leaf one level up
    355     //MoleculeLeafClass *DownLeaf;      //!< First leaf one level down
    356     MoleculeLeafClass *previous;  //!< Previous leaf on this level
    357     MoleculeLeafClass *next;      //!< Next leaf on this level
    358 
    359   //MoleculeLeafClass(MoleculeLeafClass *Up, MoleculeLeafClass *Previous);
    360   MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf);
    361   ~MoleculeLeafClass();
    362 
    363   bool AddLeaf(molecule *ptr, MoleculeLeafClass *Previous);
    364   bool FillBondStructureFromReference(ofstream *out, molecule *reference, int &FragmentCounter, atom ***&ListOfLocalAtoms, bool FreeList = false);
    365   bool FillRootStackForSubgraphs(ofstream *out, KeyStack *&RootStack, bool *AtomMask, int &FragmentCounter);
    366   bool AssignKeySetsToFragment(ofstream *out, molecule *reference, Graph *KeySetList, atom ***&ListOfLocalAtoms, Graph **&FragmentList, int &FragmentCounter, bool FreeList = false);
    367   bool FillListOfLocalAtoms(ofstream *out, atom ***&ListOfLocalAtoms, const int FragmentCounter, const int GlobalAtomCount, bool &FreeList);
    368   void TranslateIndicesToGlobalIDs(ofstream *out, Graph **FragmentList, int &FragmentCounter, int &TotalNumberOfKeySets, Graph &TotalGraph);
    369   int Count() const;
     350        public:
     351                molecule *Leaf;                                                                  //!< molecule of this leaf
     352                //MoleculeLeafClass *UpLeaf;                            //!< Leaf one level up
     353                //MoleculeLeafClass *DownLeaf;                  //!< First leaf one level down
     354                MoleculeLeafClass *previous;    //!< Previous leaf on this level
     355                MoleculeLeafClass *next;                        //!< Next leaf on this level
     356
     357        //MoleculeLeafClass(MoleculeLeafClass *Up, MoleculeLeafClass *Previous);
     358        MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf);
     359        ~MoleculeLeafClass();
     360
     361        bool AddLeaf(molecule *ptr, MoleculeLeafClass *Previous);
     362        bool FillBondStructureFromReference(ofstream *out, molecule *reference, int &FragmentCounter, atom ***&ListOfLocalAtoms, bool FreeList = false);
     363        bool FillRootStackForSubgraphs(ofstream *out, KeyStack *&RootStack, bool *AtomMask, int &FragmentCounter);
     364        bool AssignKeySetsToFragment(ofstream *out, molecule *reference, Graph *KeySetList, atom ***&ListOfLocalAtoms, Graph **&FragmentList, int &FragmentCounter, bool FreeList = false);
     365        bool FillListOfLocalAtoms(ofstream *out, atom ***&ListOfLocalAtoms, const int FragmentCounter, const int GlobalAtomCount, bool &FreeList);
     366        void TranslateIndicesToGlobalIDs(ofstream *out, Graph **FragmentList, int &FragmentCounter, int &TotalNumberOfKeySets, Graph &TotalGraph);
     367        int Count() const;
    370368};
    371369
     
    374372 */
    375373class config {
    376   public:
    377     int PsiType;
    378     int MaxPsiDouble;
    379     int PsiMaxNoUp;
    380     int PsiMaxNoDown;
    381     int MaxMinStopStep;
    382     int InitMaxMinStopStep;
    383     int ProcPEGamma;
    384     int ProcPEPsi;
    385     char *configpath;
    386     char *configname;
    387     bool FastParsing;
    388     double Deltat;
    389 
    390     private:
    391     char *mainname;
    392     char *defaultpath;
    393     char *pseudopotpath;
    394 
    395     int DoOutVis;
    396     int DoOutMes;
    397     int DoOutNICS;
    398     int DoOutOrbitals;
    399     int DoOutCurrent;
    400     int DoFullCurrent;
    401     int DoPerturbation;
    402     int DoWannier;
    403     int CommonWannier;
    404     double SawtoothStart;
    405     int VectorPlane;
    406     double VectorCut;
    407     int UseAddGramSch;
    408     int Seed;
    409 
    410     int MaxOuterStep;
    411     int OutVisStep;
    412     int OutSrcStep;
    413     double TargetTemp;
    414     int ScaleTempStep;
    415     int MaxPsiStep;
    416     double EpsWannier;
    417 
    418     int MaxMinStep;
    419     double RelEpsTotalEnergy;
    420     double RelEpsKineticEnergy;
    421     int MaxMinGapStopStep;
    422     int MaxInitMinStep;
    423     double InitRelEpsTotalEnergy;
    424     double InitRelEpsKineticEnergy;
    425     int InitMaxMinGapStopStep;
    426 
    427     //double BoxLength[NDIM*NDIM];
    428 
    429     double ECut;
    430     int MaxLevel;
    431     int RiemannTensor;
    432     int LevRFactor;
    433     int RiemannLevel;
    434     int Lev0Factor;
    435     int RTActualUse;
    436     int AddPsis;
    437 
    438     double RCut;
    439     int StructOpt;
    440     int IsAngstroem;
    441     int RelativeCoord;
    442     int MaxTypes;
    443 
    444 
    445   int ParseForParameter(int verbose, ifstream *file, const char *name, int sequential, int const xth, int const yth, int type, void *value, int repetition, int critical);
    446 
    447   public:
    448   config();
    449   ~config();
    450 
    451   int TestSyntax(char *filename, periodentafel *periode, molecule *mol);
    452   void Load(char *filename, periodentafel *periode, molecule *mol);
    453   void LoadOld(char *filename, periodentafel *periode, molecule *mol);
    454   void RetrieveConfigPathAndName(string filename);
    455   bool Save(const char *filename, periodentafel *periode, molecule *mol) const;
    456   bool SaveMPQC(const char *filename, molecule *mol) const;
    457   void Edit(molecule *mol);
    458   bool GetIsAngstroem() const;
    459   char *GetDefaultPath() const;
    460   void SetDefaultPath(const char *path);
     374        public:
     375                int PsiType;
     376                int MaxPsiDouble;
     377                int PsiMaxNoUp;
     378                int PsiMaxNoDown;
     379                int MaxMinStopStep;
     380                int InitMaxMinStopStep;
     381                int ProcPEGamma;
     382                int ProcPEPsi;
     383                char *configpath;
     384                char *configname;
     385                bool FastParsing;
     386                double Deltat;
     387
     388                private:
     389                char *mainname;
     390                char *defaultpath;
     391                char *pseudopotpath;
     392
     393                int DoOutVis;
     394                int DoOutMes;
     395                int DoOutNICS;
     396                int DoOutOrbitals;
     397                int DoOutCurrent;
     398                int DoFullCurrent;
     399                int DoPerturbation;
     400                int DoWannier;
     401                int CommonWannier;
     402                double SawtoothStart;
     403                int VectorPlane;
     404                double VectorCut;
     405                int UseAddGramSch;
     406                int Seed;
     407
     408                int MaxOuterStep;
     409                int OutVisStep;
     410                int OutSrcStep;
     411                double TargetTemp;
     412                int ScaleTempStep;
     413                int MaxPsiStep;
     414                double EpsWannier;
     415
     416                int MaxMinStep;
     417                double RelEpsTotalEnergy;
     418                double RelEpsKineticEnergy;
     419                int MaxMinGapStopStep;
     420                int MaxInitMinStep;
     421                double InitRelEpsTotalEnergy;
     422                double InitRelEpsKineticEnergy;
     423                int InitMaxMinGapStopStep;
     424
     425                //double BoxLength[NDIM*NDIM];
     426
     427                double ECut;
     428                int MaxLevel;
     429                int RiemannTensor;
     430                int LevRFactor;
     431                int RiemannLevel;
     432                int Lev0Factor;
     433                int RTActualUse;
     434                int AddPsis;
     435
     436                double RCut;
     437                int StructOpt;
     438                int IsAngstroem;
     439                int RelativeCoord;
     440                int MaxTypes;
     441
     442
     443        int ParseForParameter(int verbose, ifstream *file, const char *name, int sequential, int const xth, int const yth, int type, void *value, int repetition, int critical);
     444
     445        public:
     446        config();
     447        ~config();
     448
     449        int TestSyntax(char *filename, periodentafel *periode, molecule *mol);
     450        void Load(char *filename, periodentafel *periode, molecule *mol);
     451        void LoadOld(char *filename, periodentafel *periode, molecule *mol);
     452        void RetrieveConfigPathAndName(string filename);
     453        bool Save(const char *filename, periodentafel *periode, molecule *mol) const;
     454        bool SaveMPQC(const char *filename, molecule *mol) const;
     455        void Edit(molecule *mol);
     456        bool GetIsAngstroem() const;
     457        char *GetDefaultPath() const;
     458        void SetDefaultPath(const char *path);
    461459};
    462460
  • src/orbitals.db

    • Property mode changed from 100644 to 100755
  • src/parser.cpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    22 *
    33 * Declarations of various class functions for the parsing of value files.
    4  *   
     4 *
    55 */
    66
    77// ======================================= INCLUDES ==========================================
    88
    9 #include "helpers.hpp" 
     9#include "helpers.hpp"
    1010#include "parser.hpp"
    1111
     
    2424bool FilePresent(const char *filename, bool test)
    2525{
    26   ifstream input;
    27  
    28   input.open(filename, ios::in);
    29   if (input == NULL) {
    30     if (!test)
    31       cout << endl << "Unable to open " << filename << ", is the directory correct?" << endl;
    32     return false;
    33   }
    34   input.close();
    35   return true;
     26        ifstream input;
     27
     28        input.open(filename, ios::in);
     29        if (input == NULL) {
     30                if (!test)
     31                        cout << endl << "Unable to open " << filename << ", is the directory correct?" << endl;
     32                return false;
     33        }
     34        input.close();
     35        return true;
    3636};
    3737
     
    4343bool TestParams(int argc, char **argv)
    4444{
    45   ifstream input;
    46   stringstream line;
    47 
    48   line << argv[1] << FRAGMENTPREFIX << KEYSETFILE;
    49   return FilePresent(line.str().c_str(), false);
     45        ifstream input;
     46        stringstream line;
     47
     48        line << argv[1] << FRAGMENTPREFIX << KEYSETFILE;
     49        return FilePresent(line.str().c_str(), false);
    5050};
    5151
     
    5555 */
    5656MatrixContainer::MatrixContainer() {
    57   Indices = NULL;
    58   Header = (char *) Malloc(sizeof(char)*1023, "MatrixContainer::MatrixContainer: *Header");
    59   Matrix = (double ***) Malloc(sizeof(double **)*(1), "MatrixContainer::MatrixContainer: ***Matrix"); // one more each for the total molecule
    60   RowCounter = (int *) Malloc(sizeof(int)*(1), "MatrixContainer::MatrixContainer: *RowCounter");
    61   Matrix[0] = NULL;
    62   RowCounter[0] = -1;
    63   MatrixCounter = 0;
    64   ColumnCounter = 0;
     57        Indices = NULL;
     58        Header = (char *) Malloc(sizeof(char)*1023, "MatrixContainer::MatrixContainer: *Header");
     59        Matrix = (double ***) Malloc(sizeof(double **)*(1), "MatrixContainer::MatrixContainer: ***Matrix"); // one more each for the total molecule
     60        RowCounter = (int *) Malloc(sizeof(int)*(1), "MatrixContainer::MatrixContainer: *RowCounter");
     61        Matrix[0] = NULL;
     62        RowCounter[0] = -1;
     63        MatrixCounter = 0;
     64        ColumnCounter = 0;
    6565};
    6666
     
    6868 */
    6969MatrixContainer::~MatrixContainer() {
    70   if (Matrix != NULL) {
    71     for(int i=MatrixCounter;i--;) {
    72       if (RowCounter != NULL) {
    73           for(int j=RowCounter[i]+1;j--;)
    74             Free((void **)&Matrix[i][j], "MatrixContainer::~MatrixContainer: *Matrix[][]");
    75         Free((void **)&Matrix[i], "MatrixContainer::~MatrixContainer: **Matrix[]");
    76       }
    77     }
    78     if ((RowCounter != NULL) && (Matrix[MatrixCounter] != NULL))
    79       for(int j=RowCounter[MatrixCounter]+1;j--;)
    80         Free((void **)&Matrix[MatrixCounter][j], "MatrixContainer::~MatrixContainer: *Matrix[MatrixCounter][]");
    81     if (MatrixCounter != 0)
    82       Free((void **)&Matrix[MatrixCounter], "MatrixContainer::~MatrixContainer: **Matrix[MatrixCounter]");
    83     Free((void **)&Matrix, "MatrixContainer::~MatrixContainer: ***Matrix");
    84   }
    85   if (Indices != NULL)
    86     for(int i=MatrixCounter+1;i--;) {
    87       Free((void **)&Indices[i], "MatrixContainer::~MatrixContainer: *Indices[]");
    88     }
    89   Free((void **)&Indices, "MatrixContainer::~MatrixContainer: **Indices");
    90  
    91   Free((void **)&Header, "MatrixContainer::~MatrixContainer: *Header");
    92   Free((void **)&RowCounter, "MatrixContainer::~MatrixContainer: *RowCounter");
     70        if (Matrix != NULL) {
     71                for(int i=MatrixCounter;i--;) {
     72                        if (RowCounter != NULL) {
     73                                        for(int j=RowCounter[i]+1;j--;)
     74                                                Free((void **)&Matrix[i][j], "MatrixContainer::~MatrixContainer: *Matrix[][]");
     75                                Free((void **)&Matrix[i], "MatrixContainer::~MatrixContainer: **Matrix[]");
     76                        }
     77                }
     78                if ((RowCounter != NULL) && (Matrix[MatrixCounter] != NULL))
     79                        for(int j=RowCounter[MatrixCounter]+1;j--;)
     80                                Free((void **)&Matrix[MatrixCounter][j], "MatrixContainer::~MatrixContainer: *Matrix[MatrixCounter][]");
     81                if (MatrixCounter != 0)
     82                        Free((void **)&Matrix[MatrixCounter], "MatrixContainer::~MatrixContainer: **Matrix[MatrixCounter]");
     83                Free((void **)&Matrix, "MatrixContainer::~MatrixContainer: ***Matrix");
     84        }
     85        if (Indices != NULL)
     86                for(int i=MatrixCounter+1;i--;) {
     87                        Free((void **)&Indices[i], "MatrixContainer::~MatrixContainer: *Indices[]");
     88                }
     89        Free((void **)&Indices, "MatrixContainer::~MatrixContainer: **Indices");
     90
     91        Free((void **)&Header, "MatrixContainer::~MatrixContainer: *Header");
     92        Free((void **)&RowCounter, "MatrixContainer::~MatrixContainer: *RowCounter");
    9393};
    9494
    9595
    9696/** Parsing a number of matrices.
    97  *    -# open the matrix file
    98  *    -# skip some lines (\a skiplines)
    99  *    -# scan header lines for number of columns
    100  *    -# scan lines for number of rows
    101  *    -# allocate matrix
    102  *    -# loop over found column and row counts and parse in each entry
     97 *              -# open the matrix file
     98 *              -# skip some lines (\a skiplines)
     99 *              -# scan header lines for number of columns
     100 *              -# scan lines for number of rows
     101 *              -# allocate matrix
     102 *              -# loop over found column and row counts and parse in each entry
    103103 * \param *name directory with files
    104104 * \param skiplines number of inital lines to skip
    105105 * \param skiplines number of inital columns to skip
    106106 * \param MatrixNr index number in Matrix array to parse into
    107  * \return parsing successful 
     107 * \return parsing successful
    108108 */
    109109bool MatrixContainer::ParseMatrix(const char *name, int skiplines, int skipcolumns, int MatrixNr)
    110110{
    111   ifstream input;
    112   stringstream line;
    113   string token;
    114   char filename[1023];
    115 
    116   input.open(name, ios::in);
    117   //cout << "Opening " << name << " ... "  << input << endl;
    118   if (input == NULL) {
    119     cerr << endl << "Unable to open " << name << ", is the directory correct?" << endl;
    120     return false;
    121   }
    122  
    123   // skip some initial lines
    124   for (int m=skiplines+1;m--;)
    125     input.getline(Header, 1023);
    126  
    127   // scan header for number of columns
    128   line.str(Header);
    129   for(int k=skipcolumns;k--;)
    130     line >> Header;
    131   //cout << line.str() << endl;
    132   ColumnCounter=0;
    133   while ( getline(line,token, '\t') ) {
    134     if (token.length() > 0)
    135       ColumnCounter++;
    136   }
    137   //cout << line.str() << endl;
    138   //cout << "ColumnCounter: " << ColumnCounter << "." << endl;
    139   if (ColumnCounter == 0)
    140     cerr << "ColumnCounter: " << ColumnCounter << " from file " << name << ", this is probably an error!" << endl;
    141  
    142   // scan rest for number of rows/lines
    143   RowCounter[MatrixNr]=-1;    // counts one line too much
    144   while (!input.eof()) {
    145     input.getline(filename, 1023);
    146     //cout << "Comparing: " << strncmp(filename,"MeanForce",9) << endl;
    147     RowCounter[MatrixNr]++; // then line was not last MeanForce
    148     if (strncmp(filename,"MeanForce", 9) == 0) {
    149       break;
    150     }
    151   }
    152   //cout << "RowCounter[" << MatrixNr << "]: " << RowCounter[MatrixNr] << " from file " << name << "." << endl;
    153   if (RowCounter[MatrixNr] == 0)
    154     cerr << "RowCounter[" << MatrixNr << "]: " << RowCounter[MatrixNr] << " from file " << name << ", this is probably an error!" << endl;
    155  
    156   // allocate matrix if it's not zero dimension in one direction
    157   if ((ColumnCounter > 0) && (RowCounter[MatrixNr] > -1)) {
    158     Matrix[MatrixNr] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixNr]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]");
    159  
    160     // parse in each entry for this matrix
    161     input.clear();
    162     input.seekg(ios::beg);
    163     for (int m=skiplines+1;m--;)
    164       input.getline(Header, 1023);    // skip header
    165     line.str(Header);
    166     for(int k=skipcolumns;k--;)  // skip columns in header too
    167       line >> filename;
    168     strncpy(Header, line.str().c_str(), 1023); 
    169     for(int j=0;j<RowCounter[MatrixNr];j++) {
    170       Matrix[MatrixNr][j] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[][]");
    171       input.getline(filename, 1023);
    172       stringstream lines(filename);
    173       //cout << "Matrix at level " << j << ":";// << filename << endl;
    174       for(int k=skipcolumns;k--;)
    175         lines >> filename;
    176       for(int k=0;(k<ColumnCounter) && (!lines.eof());k++) {
    177         lines >> Matrix[MatrixNr][j][k];
    178         //cout << " " << setprecision(2) << Matrix[MatrixNr][j][k];;
    179       }
    180       //cout << endl;
    181       Matrix[MatrixNr][ RowCounter[MatrixNr] ] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[RowCounter[MatrixNr]][]");
    182       for(int j=ColumnCounter;j--;)
    183         Matrix[MatrixNr][ RowCounter[MatrixNr] ][j] = 0.;
    184     }
    185   } else {
    186     cerr << "ERROR: Matrix nr. " << MatrixNr << " has column and row count of (" << ColumnCounter << "," << RowCounter[MatrixNr] << "), could not allocate nor parse!" << endl;
    187   }
    188   input.close();
    189   return true;
     111        ifstream input;
     112        stringstream line;
     113        string token;
     114        char filename[1023];
     115
     116        input.open(name, ios::in);
     117        //cout << "Opening " << name << " ... " << input << endl;
     118        if (input == NULL) {
     119                cerr << endl << "Unable to open " << name << ", is the directory correct?" << endl;
     120                return false;
     121        }
     122
     123        // skip some initial lines
     124        for (int m=skiplines+1;m--;)
     125                input.getline(Header, 1023);
     126
     127        // scan header for number of columns
     128        line.str(Header);
     129        for(int k=skipcolumns;k--;)
     130                line >> Header;
     131        //cout << line.str() << endl;
     132        ColumnCounter=0;
     133        while ( getline(line,token, '\t') ) {
     134                if (token.length() > 0)
     135                        ColumnCounter++;
     136        }
     137        //cout << line.str() << endl;
     138        //cout << "ColumnCounter: " << ColumnCounter << "." << endl;
     139        if (ColumnCounter == 0)
     140                cerr << "ColumnCounter: " << ColumnCounter << " from file " << name << ", this is probably an error!" << endl;
     141
     142        // scan rest for number of rows/lines
     143        RowCounter[MatrixNr]=-1;                // counts one line too much
     144        while (!input.eof()) {
     145                input.getline(filename, 1023);
     146                //cout << "Comparing: " << strncmp(filename,"MeanForce",9) << endl;
     147                RowCounter[MatrixNr]++; // then line was not last MeanForce
     148                if (strncmp(filename,"MeanForce", 9) == 0) {
     149                        break;
     150                }
     151        }
     152        //cout << "RowCounter[" << MatrixNr << "]: " << RowCounter[MatrixNr] << " from file " << name << "." << endl;
     153        if (RowCounter[MatrixNr] == 0)
     154                cerr << "RowCounter[" << MatrixNr << "]: " << RowCounter[MatrixNr] << " from file " << name << ", this is probably an error!" << endl;
     155
     156        // allocate matrix if it's not zero dimension in one direction
     157        if ((ColumnCounter > 0) && (RowCounter[MatrixNr] > -1)) {
     158                Matrix[MatrixNr] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixNr]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]");
     159
     160                // parse in each entry for this matrix
     161                input.clear();
     162                input.seekg(ios::beg);
     163                for (int m=skiplines+1;m--;)
     164                        input.getline(Header, 1023);            // skip header
     165                line.str(Header);
     166                for(int k=skipcolumns;k--;)     // skip columns in header too
     167                        line >> filename;
     168                strncpy(Header, line.str().c_str(), 1023);
     169                for(int j=0;j<RowCounter[MatrixNr];j++) {
     170                        Matrix[MatrixNr][j] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[][]");
     171                        input.getline(filename, 1023);
     172                        stringstream lines(filename);
     173                        //cout << "Matrix at level " << j << ":";// << filename << endl;
     174                        for(int k=skipcolumns;k--;)
     175                                lines >> filename;
     176                        for(int k=0;(k<ColumnCounter) && (!lines.eof());k++) {
     177                                lines >> Matrix[MatrixNr][j][k];
     178                                //cout << " " << setprecision(2) << Matrix[MatrixNr][j][k];;
     179                        }
     180                        //cout << endl;
     181                        Matrix[MatrixNr][ RowCounter[MatrixNr] ] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[RowCounter[MatrixNr]][]");
     182                        for(int j=ColumnCounter;j--;)
     183                                Matrix[MatrixNr][ RowCounter[MatrixNr] ][j] = 0.;
     184                }
     185        } else {
     186                cerr << "ERROR: Matrix nr. " << MatrixNr << " has column and row count of (" << ColumnCounter << "," << RowCounter[MatrixNr] << "), could not allocate nor parse!" << endl;
     187        }
     188        input.close();
     189        return true;
    190190};
    191191
    192192/** Parsing a number of matrices.
    193193 * -# First, count the number of matrices by counting lines in KEYSETFILE
    194  * -# Then, 
    195  *    -# construct the fragment number
    196  *    -# open the matrix file
    197  *    -# skip some lines (\a skiplines)
    198  *    -# scan header lines for number of columns
    199  *    -# scan lines for number of rows
    200  *    -# allocate matrix
    201  *    -# loop over found column and row counts and parse in each entry
    202  * -# Finally, allocate one additional matrix (\a MatrixCounter) containing combined or temporary values 
     194 * -# Then,
     195 *              -# construct the fragment number
     196 *              -# open the matrix file
     197 *              -# skip some lines (\a skiplines)
     198 *              -# scan header lines for number of columns
     199 *              -# scan lines for number of rows
     200 *              -# allocate matrix
     201 *              -# loop over found column and row counts and parse in each entry
     202 * -# Finally, allocate one additional matrix (\a MatrixCounter) containing combined or temporary values
    203203 * \param *name directory with files
    204204 * \param *prefix prefix of each matrix file
     
    206206 * \param skiplines number of inital lines to skip
    207207 * \param skiplines number of inital columns to skip
    208  * \return parsing successful 
     208 * \return parsing successful
    209209 */
    210210bool MatrixContainer::ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns)
    211211{
    212   char filename[1023];
    213   ifstream input;
    214   char *FragmentNumber = NULL;
    215   stringstream file;
    216   string token;
    217  
    218   // count the number of matrices
    219   MatrixCounter = -1; // we count one too much
    220   file << name << FRAGMENTPREFIX << KEYSETFILE;
    221   input.open(file.str().c_str(), ios::in);
    222   if (input == NULL) {
    223     cout << endl << "Unable to open " << file.str() << ", is the directory correct?" << endl;
    224     return false;
    225   }
    226   while (!input.eof()) {
    227     input.getline(filename, 1023);
    228     stringstream zeile(filename);
    229     MatrixCounter++;
    230   }
    231   input.close(); 
    232   cout << "Determined " << MatrixCounter << " fragments." << endl;
    233  
    234   cout << "Parsing through each fragment and retrieving " << prefix << suffix << "." << endl;
    235   Matrix = (double ***) ReAlloc(Matrix, sizeof(double **)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: ***Matrix"); // one more each for the total molecule
    236   RowCounter = (int *) ReAlloc(RowCounter, sizeof(int)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: *RowCounter");
    237   for(int i=MatrixCounter+1;i--;) {
    238     Matrix[i] = NULL;
    239     RowCounter[i] = -1;
    240   }
    241   for(int i=0; i < MatrixCounter;i++) {
    242     // open matrix file
    243     FragmentNumber = FixedDigitNumber(MatrixCounter, i);
    244     file.str(" ");
    245     file << name << FRAGMENTPREFIX << FragmentNumber << prefix << suffix;
    246     if (!ParseMatrix(file.str().c_str(), skiplines, skipcolumns, i))
    247       return false;
    248     Free((void **)&FragmentNumber, "MatrixContainer::ParseFragmentMatrix: *FragmentNumber");
    249   }
    250   return true;
     212        char filename[1023];
     213        ifstream input;
     214        char *FragmentNumber = NULL;
     215        stringstream file;
     216        string token;
     217
     218        // count the number of matrices
     219        MatrixCounter = -1; // we count one too much
     220        file << name << FRAGMENTPREFIX << KEYSETFILE;
     221        input.open(file.str().c_str(), ios::in);
     222        if (input == NULL) {
     223                cout << endl << "Unable to open " << file.str() << ", is the directory correct?" << endl;
     224                return false;
     225        }
     226        while (!input.eof()) {
     227                input.getline(filename, 1023);
     228                stringstream zeile(filename);
     229                MatrixCounter++;
     230        }
     231        input.close();
     232        cout << "Determined " << MatrixCounter << " fragments." << endl;
     233
     234        cout << "Parsing through each fragment and retrieving " << prefix << suffix << "." << endl;
     235        Matrix = (double ***) ReAlloc(Matrix, sizeof(double **)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: ***Matrix"); // one more each for the total molecule
     236        RowCounter = (int *) ReAlloc(RowCounter, sizeof(int)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: *RowCounter");
     237        for(int i=MatrixCounter+1;i--;) {
     238                Matrix[i] = NULL;
     239                RowCounter[i] = -1;
     240        }
     241        for(int i=0; i < MatrixCounter;i++) {
     242                // open matrix file
     243                FragmentNumber = FixedDigitNumber(MatrixCounter, i);
     244                file.str(" ");
     245                file << name << FRAGMENTPREFIX << FragmentNumber << prefix << suffix;
     246                if (!ParseMatrix(file.str().c_str(), skiplines, skipcolumns, i))
     247                        return false;
     248                Free((void **)&FragmentNumber, "MatrixContainer::ParseFragmentMatrix: *FragmentNumber");
     249        }
     250        return true;
    251251};
    252252
     
    256256 * \param *RCounter number of rows for each matrix
    257257 * \param CCounter number of columns for all matrices
    258  * \return Allocation successful 
     258 * \return Allocation successful
    259259 */
    260260bool MatrixContainer::AllocateMatrix(char *GivenHeader, int MCounter, int *RCounter, int CCounter)
    261261{
    262   Header = (char *) Malloc(sizeof(char)*1024, "MatrixContainer::ParseFragmentMatrix: *EnergyHeader");
    263   strncpy(Header, GivenHeader, 1023);
    264 
    265   MatrixCounter = MCounter;
    266   ColumnCounter = CCounter;
    267   Matrix = (double ***) Malloc(sizeof(double **)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: ***Matrix"); // one more each for the total molecule
    268   RowCounter = (int *) Malloc(sizeof(int)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: *RowCounter");
    269   for(int i=MatrixCounter+1;i--;) {
    270     RowCounter[i] = RCounter[i];
    271     Matrix[i] = (double **) Malloc(sizeof(double *)*(RowCounter[i]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]"); 
    272     for(int j=RowCounter[i]+1;j--;) {
    273       Matrix[i][j] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[][]");
    274       for(int k=ColumnCounter;k--;)
    275         Matrix[i][j][k] = 0.;
    276     }
    277   }
    278   return true;
     262        Header = (char *) Malloc(sizeof(char)*1024, "MatrixContainer::ParseFragmentMatrix: *EnergyHeader");
     263        strncpy(Header, GivenHeader, 1023);
     264
     265        MatrixCounter = MCounter;
     266        ColumnCounter = CCounter;
     267        Matrix = (double ***) Malloc(sizeof(double **)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: ***Matrix"); // one more each for the total molecule
     268        RowCounter = (int *) Malloc(sizeof(int)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: *RowCounter");
     269        for(int i=MatrixCounter+1;i--;) {
     270                RowCounter[i] = RCounter[i];
     271                Matrix[i] = (double **) Malloc(sizeof(double *)*(RowCounter[i]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]");
     272                for(int j=RowCounter[i]+1;j--;) {
     273                        Matrix[i][j] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[][]");
     274                        for(int k=ColumnCounter;k--;)
     275                                Matrix[i][j][k] = 0.;
     276                }
     277        }
     278        return true;
    279279};
    280280
     
    284284bool MatrixContainer::ResetMatrix()
    285285{
    286   for(int i=MatrixCounter+1;i--;)
    287     for(int j=RowCounter[i]+1;j--;)
    288       for(int k=ColumnCounter;k--;)
    289         Matrix[i][j][k] = 0.;
    290   return true;
     286        for(int i=MatrixCounter+1;i--;)
     287                for(int j=RowCounter[i]+1;j--;)
     288                        for(int k=ColumnCounter;k--;)
     289                                Matrix[i][j][k] = 0.;
     290        return true;
    291291};
    292292
     
    296296double MatrixContainer::FindMaxValue()
    297297{
    298   double max = Matrix[0][0][0];
    299   for(int i=MatrixCounter+1;i--;)
    300     for(int j=RowCounter[i]+1;j--;)
    301       for(int k=ColumnCounter;k--;)
    302         if (fabs(Matrix[i][j][k]) > max)
    303           max = fabs(Matrix[i][j][k]);
    304   if (fabs(max) < MYEPSILON)
    305     max += MYEPSILON;
     298        double max = Matrix[0][0][0];
     299        for(int i=MatrixCounter+1;i--;)
     300                for(int j=RowCounter[i]+1;j--;)
     301                        for(int k=ColumnCounter;k--;)
     302                                if (fabs(Matrix[i][j][k]) > max)
     303                                        max = fabs(Matrix[i][j][k]);
     304        if (fabs(max) < MYEPSILON)
     305                max += MYEPSILON;
    306306 return max;
    307307};
     
    312312double MatrixContainer::FindMinValue()
    313313{
    314   double min = Matrix[0][0][0];
    315   for(int i=MatrixCounter+1;i--;)
    316     for(int j=RowCounter[i]+1;j--;)
    317       for(int k=ColumnCounter;k--;)
    318         if (fabs(Matrix[i][j][k]) < min)
    319           min = fabs(Matrix[i][j][k]);
    320   if (fabs(min) < MYEPSILON)
    321     min += MYEPSILON;
    322   return min;
     314        double min = Matrix[0][0][0];
     315        for(int i=MatrixCounter+1;i--;)
     316                for(int j=RowCounter[i]+1;j--;)
     317                        for(int k=ColumnCounter;k--;)
     318                                if (fabs(Matrix[i][j][k]) < min)
     319                                        min = fabs(Matrix[i][j][k]);
     320        if (fabs(min) < MYEPSILON)
     321                min += MYEPSILON;
     322        return min;
    323323};
    324324
     
    330330bool MatrixContainer::SetLastMatrix(double value, int skipcolumns)
    331331{
    332   for(int j=RowCounter[MatrixCounter]+1;j--;)
    333     for(int k=skipcolumns;k<ColumnCounter;k++)
    334       Matrix[MatrixCounter][j][k] = value;
    335   return true;
     332        for(int j=RowCounter[MatrixCounter]+1;j--;)
     333                for(int k=skipcolumns;k<ColumnCounter;k++)
     334                        Matrix[MatrixCounter][j][k] = value;
     335        return true;
    336336};
    337337
     
    343343bool MatrixContainer::SetLastMatrix(double **values, int skipcolumns)
    344344{
    345   for(int j=RowCounter[MatrixCounter]+1;j--;)
    346     for(int k=skipcolumns;k<ColumnCounter;k++)
    347       Matrix[MatrixCounter][j][k] = values[j][k];
    348   return true;
     345        for(int j=RowCounter[MatrixCounter]+1;j--;)
     346                for(int k=skipcolumns;k<ColumnCounter;k++)
     347                        Matrix[MatrixCounter][j][k] = values[j][k];
     348        return true;
    349349};
    350350
     
    358358bool MatrixContainer::SumSubManyBodyTerms(class MatrixContainer &MatrixValues, class KeySetsContainer &KeySet, int Order)
    359359{
    360   // go through each order
    361   for (int CurrentFragment=0;CurrentFragment<KeySet.FragmentsPerOrder[Order];CurrentFragment++) {
    362     //cout << "Current Fragment is " << CurrentFragment << "/" << KeySet.OrderSet[Order][CurrentFragment] << "." << endl;
    363     // then go per order through each suborder and pick together all the terms that contain this fragment
    364     for(int SubOrder=0;SubOrder<=Order;SubOrder++) { // go through all suborders up to the desired order
    365       for (int j=0;j<KeySet.FragmentsPerOrder[SubOrder];j++) { // go through all possible fragments of size suborder
    366         if (KeySet.Contains(KeySet.OrderSet[Order][CurrentFragment], KeySet.OrderSet[SubOrder][j])) {
    367           //cout << "Current other fragment is " << j << "/" << KeySet.OrderSet[SubOrder][j] << "." << endl;
    368           // if the fragment's indices are all in the current fragment
    369           for(int k=0;k<RowCounter[ KeySet.OrderSet[SubOrder][j] ];k++) { // go through all atoms in this fragment
    370             int m = MatrixValues.Indices[ KeySet.OrderSet[SubOrder][j] ][k];
    371             //cout << "Current index is " << k << "/" << m << "." << endl;
    372             if (m != -1) { // if it's not an added hydrogen
    373               for (int l=0;l<RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ];l++) { // look for the corresponding index in the current fragment
    374                 //cout << "Comparing " << m << " with " << MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][l] << "." << endl;
    375                 if (m == MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][l]) {
    376                   m = l;
    377                   break; 
    378                 }
    379               }
    380               //cout << "Corresponding index in CurrentFragment is " << m << "." << endl;
    381               if (m > RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ]) {
    382                 cerr << "In fragment No. " << KeySet.OrderSet[Order][CurrentFragment]  << " current force index " << m << " is greater than " << RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ] << "!" << endl;
    383                 return false;
    384               }
    385               if (Order == SubOrder) { // equal order is always copy from Energies
    386                 for(int l=ColumnCounter;l--;) // then adds/subtract each column
    387                   Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][l] += MatrixValues.Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l];
    388               } else {
    389                 for(int l=ColumnCounter;l--;)
    390                   Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][l] -= Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l];
    391               }
    392             }
    393             //if ((ColumnCounter>1) && (RowCounter[0]-1 >= 1))
    394              //cout << "Fragments[ KeySet.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySet.OrderSet[Order][CurrentFragment] << " ][" << RowCounter[0]-1 << "][" << 1 << "] = " <<  Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][RowCounter[0]-1][1] << endl;
    395           }
    396         } else {
    397           //cout << "Fragment " << KeySet.OrderSet[SubOrder][j] << " is not contained in fragment " << KeySet.OrderSet[Order][CurrentFragment] << "." << endl;
    398         }
    399       }
    400     }
    401    //cout << "Final Fragments[ KeySet.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySet.OrderSet[Order][CurrentFragment] << " ][" << KeySet.AtomCounter[0]-1 << "][" << 1 << "] = " <<  Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][KeySet.AtomCounter[0]-1][1] << endl;
    402   }
    403  
    404   return true;
     360        // go through each order
     361        for (int CurrentFragment=0;CurrentFragment<KeySet.FragmentsPerOrder[Order];CurrentFragment++) {
     362                //cout << "Current Fragment is " << CurrentFragment << "/" << KeySet.OrderSet[Order][CurrentFragment] << "." << endl;
     363                // then go per order through each suborder and pick together all the terms that contain this fragment
     364                for(int SubOrder=0;SubOrder<=Order;SubOrder++) { // go through all suborders up to the desired order
     365                        for (int j=0;j<KeySet.FragmentsPerOrder[SubOrder];j++) { // go through all possible fragments of size suborder
     366                                if (KeySet.Contains(KeySet.OrderSet[Order][CurrentFragment], KeySet.OrderSet[SubOrder][j])) {
     367                                        //cout << "Current other fragment is " << j << "/" << KeySet.OrderSet[SubOrder][j] << "." << endl;
     368                                        // if the fragment's indices are all in the current fragment
     369                                        for(int k=0;k<RowCounter[ KeySet.OrderSet[SubOrder][j] ];k++) { // go through all atoms in this fragment
     370                                                int m = MatrixValues.Indices[ KeySet.OrderSet[SubOrder][j] ][k];
     371                                                //cout << "Current index is " << k << "/" << m << "." << endl;
     372                                                if (m != -1) { // if it's not an added hydrogen
     373                                                        for (int l=0;l<RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ];l++) { // look for the corresponding index in the current fragment
     374                                                                //cout << "Comparing " << m << " with " << MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][l] << "." << endl;
     375                                                                if (m == MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][l]) {
     376                                                                        m = l;
     377                                                                        break;
     378                                                                }
     379                                                        }
     380                                                        //cout << "Corresponding index in CurrentFragment is " << m << "." << endl;
     381                                                        if (m > RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ]) {
     382                                                                cerr << "In fragment No. " << KeySet.OrderSet[Order][CurrentFragment]    << " current force index " << m << " is greater than " << RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ] << "!" << endl;
     383                                                                return false;
     384                                                        }
     385                                                        if (Order == SubOrder) { // equal order is always copy from Energies
     386                                                                for(int l=ColumnCounter;l--;) // then adds/subtract each column
     387                                                                        Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][l] += MatrixValues.Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l];
     388                                                        } else {
     389                                                                for(int l=ColumnCounter;l--;)
     390                                                                        Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][l] -= Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l];
     391                                                        }
     392                                                }
     393                                                //if ((ColumnCounter>1) && (RowCounter[0]-1 >= 1))
     394                                                 //cout << "Fragments[ KeySet.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySet.OrderSet[Order][CurrentFragment] << " ][" << RowCounter[0]-1 << "][" << 1 << "] = " <<   Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][RowCounter[0]-1][1] << endl;
     395                                        }
     396                                } else {
     397                                        //cout << "Fragment " << KeySet.OrderSet[SubOrder][j] << " is not contained in fragment " << KeySet.OrderSet[Order][CurrentFragment] << "." << endl;
     398                                }
     399                        }
     400                }
     401         //cout << "Final Fragments[ KeySet.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySet.OrderSet[Order][CurrentFragment] << " ][" << KeySet.AtomCounter[0]-1 << "][" << 1 << "] = " <<     Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][KeySet.AtomCounter[0]-1][1] << endl;
     402        }
     403
     404        return true;
    405405};
    406406
     
    412412bool MatrixContainer::WriteTotalFragments(const char *name, const char *prefix)
    413413{
    414   ofstream output;
    415   char *FragmentNumber = NULL;
    416 
    417   cout << "Writing fragment files." << endl;
    418   for(int i=0;i<MatrixCounter;i++) {
    419     stringstream line;
    420     FragmentNumber = FixedDigitNumber(MatrixCounter, i);
    421     line << name << FRAGMENTPREFIX << FragmentNumber << "/" << prefix;
    422     Free((void **)&FragmentNumber, "*FragmentNumber");
    423     output.open(line.str().c_str(), ios::out);
    424     if (output == NULL) {
    425       cerr << "Unable to open output energy file " << line.str() << "!" << endl;
    426       return false;
    427     }
    428     output << Header << endl;
    429     for(int j=0;j<RowCounter[i];j++) {
    430       for(int k=0;k<ColumnCounter;k++)
    431         output << scientific << Matrix[i][j][k] << "\t";
    432       output << endl;
    433     }
    434     output.close();
    435   }
    436   return true;
     414        ofstream output;
     415        char *FragmentNumber = NULL;
     416
     417        cout << "Writing fragment files." << endl;
     418        for(int i=0;i<MatrixCounter;i++) {
     419                stringstream line;
     420                FragmentNumber = FixedDigitNumber(MatrixCounter, i);
     421                line << name << FRAGMENTPREFIX << FragmentNumber << "/" << prefix;
     422                Free((void **)&FragmentNumber, "*FragmentNumber");
     423                output.open(line.str().c_str(), ios::out);
     424                if (output == NULL) {
     425                        cerr << "Unable to open output energy file " << line.str() << "!" << endl;
     426                        return false;
     427                }
     428                output << Header << endl;
     429                for(int j=0;j<RowCounter[i];j++) {
     430                        for(int k=0;k<ColumnCounter;k++)
     431                                output << scientific << Matrix[i][j][k] << "\t";
     432                        output << endl;
     433                }
     434                output.close();
     435        }
     436        return true;
    437437};
    438438
     
    445445bool MatrixContainer::WriteLastMatrix(const char *name, const char *prefix, const char *suffix)
    446446{
    447   ofstream output;
    448   stringstream line;
    449 
    450   cout << "Writing matrix values of " << suffix << "." << endl;
    451   line << name << prefix << suffix;
    452   output.open(line.str().c_str(), ios::out);
    453   if (output == NULL) {
    454     cerr << "Unable to open output matrix file " << line.str() << "!" << endl;
    455     return false;
    456   }
    457   output << Header << endl;
    458   for(int j=0;j<RowCounter[MatrixCounter];j++) {
    459     for(int k=0;k<ColumnCounter;k++)
    460       output << scientific << Matrix[MatrixCounter][j][k] << "\t";
    461     output << endl;
    462   }
    463   output.close();
    464   return true;
     447        ofstream output;
     448        stringstream line;
     449
     450        cout << "Writing matrix values of " << suffix << "." << endl;
     451        line << name << prefix << suffix;
     452        output.open(line.str().c_str(), ios::out);
     453        if (output == NULL) {
     454                cerr << "Unable to open output matrix file " << line.str() << "!" << endl;
     455                return false;
     456        }
     457        output << Header << endl;
     458        for(int j=0;j<RowCounter[MatrixCounter];j++) {
     459                for(int k=0;k<ColumnCounter;k++)
     460                        output << scientific << Matrix[MatrixCounter][j][k] << "\t";
     461                output << endl;
     462        }
     463        output.close();
     464        return true;
    465465};
    466466
     
    471471 * \return creation sucessful
    472472 */
    473 bool EnergyMatrix::ParseIndices() 
    474 {
    475   cout << "Parsing energy indices." << endl;
    476   Indices = (int **) Malloc(sizeof(int *)*(MatrixCounter+1), "EnergyMatrix::ParseIndices: **Indices");
    477   for(int i=MatrixCounter+1;i--;) {
    478     Indices[i] = (int *) Malloc(sizeof(int)*RowCounter[i], "EnergyMatrix::ParseIndices: *Indices[]");
    479     for(int j=RowCounter[i];j--;)
    480       Indices[i][j] = j;
    481   }
    482   return true;
     473bool EnergyMatrix::ParseIndices()
     474{
     475        cout << "Parsing energy indices." << endl;
     476        Indices = (int **) Malloc(sizeof(int *)*(MatrixCounter+1), "EnergyMatrix::ParseIndices: **Indices");
     477        for(int i=MatrixCounter+1;i--;) {
     478                Indices[i] = (int *) Malloc(sizeof(int)*RowCounter[i], "EnergyMatrix::ParseIndices: *Indices[]");
     479                for(int j=RowCounter[i];j--;)
     480                        Indices[i][j] = j;
     481        }
     482        return true;
    483483};
    484484
     
    494494bool EnergyMatrix::SumSubEnergy(class EnergyMatrix &Fragments, class EnergyMatrix *CorrectionFragments, class KeySetsContainer &KeySet, int Order, double sign)
    495495{
    496   // sum energy
    497   if (CorrectionFragments == NULL)
    498     for(int i=KeySet.FragmentsPerOrder[Order];i--;)
    499       for(int j=RowCounter[ KeySet.OrderSet[Order][i] ];j--;)
    500         for(int k=ColumnCounter;k--;)
    501           Matrix[MatrixCounter][j][k] += sign*Fragments.Matrix[ KeySet.OrderSet[Order][i] ][j][k];
    502   else
    503     for(int i=KeySet.FragmentsPerOrder[Order];i--;)
    504       for(int j=RowCounter[ KeySet.OrderSet[Order][i] ];j--;)
    505         for(int k=ColumnCounter;k--;)
    506           Matrix[MatrixCounter][j][k] += sign*(Fragments.Matrix[ KeySet.OrderSet[Order][i] ][j][k] + CorrectionFragments->Matrix[ KeySet.OrderSet[Order][i] ][j][k]);
    507   return true;
     496        // sum energy
     497        if (CorrectionFragments == NULL)
     498                for(int i=KeySet.FragmentsPerOrder[Order];i--;)
     499                        for(int j=RowCounter[ KeySet.OrderSet[Order][i] ];j--;)
     500                                for(int k=ColumnCounter;k--;)
     501                                        Matrix[MatrixCounter][j][k] += sign*Fragments.Matrix[ KeySet.OrderSet[Order][i] ][j][k];
     502        else
     503                for(int i=KeySet.FragmentsPerOrder[Order];i--;)
     504                        for(int j=RowCounter[ KeySet.OrderSet[Order][i] ];j--;)
     505                                for(int k=ColumnCounter;k--;)
     506                                        Matrix[MatrixCounter][j][k] += sign*(Fragments.Matrix[ KeySet.OrderSet[Order][i] ][j][k] + CorrectionFragments->Matrix[ KeySet.OrderSet[Order][i] ][j][k]);
     507        return true;
    508508};
    509509
     
    515515 * \param skiplines number of inital columns to skip
    516516 * \return parsing successful
    517  */ 
     517 */
    518518bool EnergyMatrix::ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns)
    519519{
    520   char filename[1024];
    521   bool status = MatrixContainer::ParseFragmentMatrix(name, prefix, suffix, skiplines, skipcolumns);
    522 
    523   if (status) {
    524     // count maximum of columns
    525     RowCounter[MatrixCounter] = 0;
    526     for(int j=0; j < MatrixCounter;j++) // (energy matrix might be bigger than number of atoms in terms of rows)
    527       if (RowCounter[j] > RowCounter[MatrixCounter])
    528         RowCounter[MatrixCounter] = RowCounter[j];
    529     // allocate last plus one matrix
    530     cout << "Allocating last plus one matrix with " << (RowCounter[MatrixCounter]+1) << " rows and " << ColumnCounter << " columns." << endl;
    531     Matrix[MatrixCounter] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixCounter]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]");
    532     for(int j=0;j<=RowCounter[MatrixCounter];j++)
    533       Matrix[MatrixCounter][j] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[][]");
    534    
    535     // try independently to parse global energysuffix file if present
    536     strncpy(filename, name, 1023);
    537     strncat(filename, prefix, 1023-strlen(filename));
    538     strncat(filename, suffix.c_str(), 1023-strlen(filename));
    539     ParseMatrix(filename, skiplines, skipcolumns, MatrixCounter);
    540   }
    541   return status;
     520        char filename[1024];
     521        bool status = MatrixContainer::ParseFragmentMatrix(name, prefix, suffix, skiplines, skipcolumns);
     522
     523        if (status) {
     524                // count maximum of columns
     525                RowCounter[MatrixCounter] = 0;
     526                for(int j=0; j < MatrixCounter;j++) // (energy matrix might be bigger than number of atoms in terms of rows)
     527                        if (RowCounter[j] > RowCounter[MatrixCounter])
     528                                RowCounter[MatrixCounter] = RowCounter[j];
     529                // allocate last plus one matrix
     530                cout << "Allocating last plus one matrix with " << (RowCounter[MatrixCounter]+1) << " rows and " << ColumnCounter << " columns." << endl;
     531                Matrix[MatrixCounter] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixCounter]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]");
     532                for(int j=0;j<=RowCounter[MatrixCounter];j++)
     533                        Matrix[MatrixCounter][j] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[][]");
     534
     535                // try independently to parse global energysuffix file if present
     536                strncpy(filename, name, 1023);
     537                strncat(filename, prefix, 1023-strlen(filename));
     538                strncat(filename, suffix.c_str(), 1023-strlen(filename));
     539                ParseMatrix(filename, skiplines, skipcolumns, MatrixCounter);
     540        }
     541        return status;
    542542};
    543543
     
    546546/** Parsing force Indices of each fragment
    547547 * \param *name directory with \a ForcesFile
    548  * \return parsing successful 
    549  */
    550 bool ForceMatrix::ParseIndices(char *name) 
    551 {
    552   ifstream input;
    553   char *FragmentNumber = NULL;
    554   char filename[1023];
    555   stringstream line;
    556  
    557   cout << "Parsing force indices for " << MatrixCounter << " matrices." << endl;
    558   Indices = (int **) Malloc(sizeof(int *)*(MatrixCounter+1), "ForceMatrix::ParseIndices: **Indices");
    559   line << name << FRAGMENTPREFIX << FORCESFILE;
    560   input.open(line.str().c_str(), ios::in);
    561   //cout << "Opening " << line.str() << " ... "  << input << endl;
    562   if (input == NULL) {
    563     cout << endl << "Unable to open " << line.str() << ", is the directory correct?" << endl;
    564     return false;
    565   }
    566   for (int i=0;(i<MatrixCounter) && (!input.eof());i++) {
    567     // get the number of atoms for this fragment
    568     input.getline(filename, 1023);
    569     line.str(filename);
    570     // parse the values
    571     Indices[i] = (int *) Malloc(sizeof(int)*RowCounter[i], "ForceMatrix::ParseIndices: *Indices[]");
    572     FragmentNumber = FixedDigitNumber(MatrixCounter, i);
    573     //cout << FRAGMENTPREFIX << FragmentNumber << "[" << RowCounter[i] << "]:";
    574     Free((void **)&FragmentNumber, "ForceMatrix::ParseIndices: *FragmentNumber");
    575     for(int j=0;(j<RowCounter[i]) && (!line.eof());j++) {
    576       line >> Indices[i][j];
    577       //cout << " " << Indices[i][j];
    578     }
    579     //cout << endl;
    580   }
    581   Indices[MatrixCounter] = (int *) Malloc(sizeof(int)*RowCounter[MatrixCounter], "ForceMatrix::ParseIndices: *Indices[]");
    582   for(int j=RowCounter[MatrixCounter];j--;) {
    583     Indices[MatrixCounter][j] = j;
    584   }
    585   input.close();
    586   return true;
     548 * \return parsing successful
     549 */
     550bool ForceMatrix::ParseIndices(char *name)
     551{
     552        ifstream input;
     553        char *FragmentNumber = NULL;
     554        char filename[1023];
     555        stringstream line;
     556
     557        cout << "Parsing force indices for " << MatrixCounter << " matrices." << endl;
     558        Indices = (int **) Malloc(sizeof(int *)*(MatrixCounter+1), "ForceMatrix::ParseIndices: **Indices");
     559        line << name << FRAGMENTPREFIX << FORCESFILE;
     560        input.open(line.str().c_str(), ios::in);
     561        //cout << "Opening " << line.str() << " ... "   << input << endl;
     562        if (input == NULL) {
     563                cout << endl << "Unable to open " << line.str() << ", is the directory correct?" << endl;
     564                return false;
     565        }
     566        for (int i=0;(i<MatrixCounter) && (!input.eof());i++) {
     567                // get the number of atoms for this fragment
     568                input.getline(filename, 1023);
     569                line.str(filename);
     570                // parse the values
     571                Indices[i] = (int *) Malloc(sizeof(int)*RowCounter[i], "ForceMatrix::ParseIndices: *Indices[]");
     572                FragmentNumber = FixedDigitNumber(MatrixCounter, i);
     573                //cout << FRAGMENTPREFIX << FragmentNumber << "[" << RowCounter[i] << "]:";
     574                Free((void **)&FragmentNumber, "ForceMatrix::ParseIndices: *FragmentNumber");
     575                for(int j=0;(j<RowCounter[i]) && (!line.eof());j++) {
     576                        line >> Indices[i][j];
     577                        //cout << " " << Indices[i][j];
     578                }
     579                //cout << endl;
     580        }
     581        Indices[MatrixCounter] = (int *) Malloc(sizeof(int)*RowCounter[MatrixCounter], "ForceMatrix::ParseIndices: *Indices[]");
     582        for(int j=RowCounter[MatrixCounter];j--;) {
     583                Indices[MatrixCounter][j] = j;
     584        }
     585        input.close();
     586        return true;
    587587};
    588588
     
    592592 * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order
    593593 * \param Order bond order
    594  *  \param sign +1 or -1
     594 *      \param sign +1 or -1
    595595 * \return true if summing was successful
    596596 */
    597597bool ForceMatrix::SumSubForces(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign)
    598598{
    599   int FragmentNr;
    600   // sum forces
    601   for(int i=0;i<KeySet.FragmentsPerOrder[Order];i++) {
    602     FragmentNr = KeySet.OrderSet[Order][i];
    603     for(int l=0;l<RowCounter[ FragmentNr ];l++) {
    604       int j = Indices[ FragmentNr ][l];
    605       if (j > RowCounter[MatrixCounter]) {
    606         cerr << "Current force index " << j << " is greater than " << RowCounter[MatrixCounter] << "!" << endl;
    607         return false;
    608       }
    609       if (j != -1) {
    610         //if (j == 0) cout << "Summing onto ion 0, type 0 from fragment " << FragmentNr << ", ion " << l << "." << endl;
    611         for(int k=2;k<ColumnCounter;k++)
    612           Matrix[MatrixCounter][j][k] += sign*Fragments.Matrix[ FragmentNr ][l][k];
    613       }
    614     }
    615   }
    616   return true;
     599        int FragmentNr;
     600        // sum forces
     601        for(int i=0;i<KeySet.FragmentsPerOrder[Order];i++) {
     602                FragmentNr = KeySet.OrderSet[Order][i];
     603                for(int l=0;l<RowCounter[ FragmentNr ];l++) {
     604                        int j = Indices[ FragmentNr ][l];
     605                        if (j > RowCounter[MatrixCounter]) {
     606                                cerr << "Current force index " << j << " is greater than " << RowCounter[MatrixCounter] << "!" << endl;
     607                                return false;
     608                        }
     609                        if (j != -1) {
     610                                //if (j == 0) cout << "Summing onto ion 0, type 0 from fragment " << FragmentNr << ", ion " << l << "." << endl;
     611                                for(int k=2;k<ColumnCounter;k++)
     612                                        Matrix[MatrixCounter][j][k] += sign*Fragments.Matrix[ FragmentNr ][l][k];
     613                        }
     614                }
     615        }
     616        return true;
    617617};
    618618
     
    625625 * \param skiplines number of inital columns to skip
    626626 * \return parsing successful
    627  */ 
     627 */
    628628bool ForceMatrix::ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns)
    629629{
    630   char filename[1023];
    631   ifstream input;
    632   stringstream file;
    633   int nr;
    634   bool status = MatrixContainer::ParseFragmentMatrix(name, prefix, suffix, skiplines, skipcolumns);
    635 
    636   if (status) {
    637     // count number of atoms for last plus one matrix
    638     file << name << FRAGMENTPREFIX << KEYSETFILE;
    639     input.open(file.str().c_str(), ios::in);
    640     if (input == NULL) {
    641       cout << endl << "Unable to open " << file.str() << ", is the directory correct?" << endl;
    642       return false;
    643     }
    644     RowCounter[MatrixCounter] = 0;
    645     while (!input.eof()) {
    646       input.getline(filename, 1023);
    647       stringstream zeile(filename);
    648       while (!zeile.eof()) {
    649         zeile >> nr;
    650         //cout << "Current index: " << nr << "." << endl;
    651         if (nr > RowCounter[MatrixCounter])
    652           RowCounter[MatrixCounter] = nr;
    653       }
    654     }
    655     RowCounter[MatrixCounter]++;    // nr start at 0, count starts at 1
    656     input.close();
    657  
    658     // allocate last plus one matrix
    659     cout << "Allocating last plus one matrix with " << (RowCounter[MatrixCounter]+1) << " rows and " << ColumnCounter << " columns." << endl;
    660     Matrix[MatrixCounter] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixCounter]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]");
    661     for(int j=0;j<=RowCounter[MatrixCounter];j++)
    662       Matrix[MatrixCounter][j] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[][]");
    663 
    664     // try independently to parse global forcesuffix file if present
    665     strncpy(filename, name, 1023);
    666     strncat(filename, prefix, 1023-strlen(filename));
    667     strncat(filename, suffix.c_str(), 1023-strlen(filename));
    668     ParseMatrix(filename, skiplines, skipcolumns, MatrixCounter);
    669   }
    670  
    671 
    672   return status;
     630        char filename[1023];
     631        ifstream input;
     632        stringstream file;
     633        int nr;
     634        bool status = MatrixContainer::ParseFragmentMatrix(name, prefix, suffix, skiplines, skipcolumns);
     635
     636        if (status) {
     637                // count number of atoms for last plus one matrix
     638                file << name << FRAGMENTPREFIX << KEYSETFILE;
     639                input.open(file.str().c_str(), ios::in);
     640                if (input == NULL) {
     641                        cout << endl << "Unable to open " << file.str() << ", is the directory correct?" << endl;
     642                        return false;
     643                }
     644                RowCounter[MatrixCounter] = 0;
     645                while (!input.eof()) {
     646                        input.getline(filename, 1023);
     647                        stringstream zeile(filename);
     648                        while (!zeile.eof()) {
     649                                zeile >> nr;
     650                                //cout << "Current index: " << nr << "." << endl;
     651                                if (nr > RowCounter[MatrixCounter])
     652                                        RowCounter[MatrixCounter] = nr;
     653                        }
     654                }
     655                RowCounter[MatrixCounter]++;            // nr start at 0, count starts at 1
     656                input.close();
     657
     658                // allocate last plus one matrix
     659                cout << "Allocating last plus one matrix with " << (RowCounter[MatrixCounter]+1) << " rows and " << ColumnCounter << " columns." << endl;
     660                Matrix[MatrixCounter] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixCounter]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]");
     661                for(int j=0;j<=RowCounter[MatrixCounter];j++)
     662                        Matrix[MatrixCounter][j] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[][]");
     663
     664                // try independently to parse global forcesuffix file if present
     665                strncpy(filename, name, 1023);
     666                strncat(filename, prefix, 1023-strlen(filename));
     667                strncat(filename, suffix.c_str(), 1023-strlen(filename));
     668                ParseMatrix(filename, skiplines, skipcolumns, MatrixCounter);
     669        }
     670
     671
     672        return status;
    673673};
    674674
     
    678678 */
    679679KeySetsContainer::KeySetsContainer() {
    680   KeySets = NULL;
    681   AtomCounter = NULL;
    682   FragmentCounter = 0;
    683   Order = 0;
    684   FragmentsPerOrder = 0;
    685   OrderSet = NULL;
     680        KeySets = NULL;
     681        AtomCounter = NULL;
     682        FragmentCounter = 0;
     683        Order = 0;
     684        FragmentsPerOrder = 0;
     685        OrderSet = NULL;
    686686};
    687687
     
    689689 */
    690690KeySetsContainer::~KeySetsContainer() {
    691   for(int i=FragmentCounter;i--;)
    692     Free((void **)&KeySets[i], "KeySetsContainer::~KeySetsContainer: *KeySets[]");
    693   for(int i=Order;i--;)
    694     Free((void **)&OrderSet[i], "KeySetsContainer::~KeySetsContainer: *OrderSet[]");
    695   Free((void **)&KeySets, "KeySetsContainer::~KeySetsContainer: **KeySets");
    696   Free((void **)&OrderSet, "KeySetsContainer::~KeySetsContainer: **OrderSet");
    697   Free((void **)&AtomCounter, "KeySetsContainer::~KeySetsContainer: *AtomCounter");
    698   Free((void **)&FragmentsPerOrder, "KeySetsContainer::~KeySetsContainer: *FragmentsPerOrder");
     691        for(int i=FragmentCounter;i--;)
     692                Free((void **)&KeySets[i], "KeySetsContainer::~KeySetsContainer: *KeySets[]");
     693        for(int i=Order;i--;)
     694                Free((void **)&OrderSet[i], "KeySetsContainer::~KeySetsContainer: *OrderSet[]");
     695        Free((void **)&KeySets, "KeySetsContainer::~KeySetsContainer: **KeySets");
     696        Free((void **)&OrderSet, "KeySetsContainer::~KeySetsContainer: **OrderSet");
     697        Free((void **)&AtomCounter, "KeySetsContainer::~KeySetsContainer: *AtomCounter");
     698        Free((void **)&FragmentsPerOrder, "KeySetsContainer::~KeySetsContainer: *FragmentsPerOrder");
    699699};
    700700
     
    706706 */
    707707bool KeySetsContainer::ParseKeySets(const char *name, const int *ACounter, const int FCounter) {
    708   ifstream input;
    709   char *FragmentNumber = NULL;
    710   stringstream file;
    711   char filename[1023];
    712  
    713   FragmentCounter = FCounter;
    714   cout << "Parsing key sets." << endl;
    715   KeySets = (int **) Malloc(sizeof(int *)*FragmentCounter, "KeySetsContainer::ParseKeySets: **KeySets");
    716   for(int i=FragmentCounter;i--;)
    717     KeySets[i] = NULL;
    718   file << name << FRAGMENTPREFIX << KEYSETFILE;
    719   input.open(file.str().c_str(), ios::in);
    720   if (input == NULL) {
    721     cout << endl << "Unable to open " << file.str() << ", is the directory correct?" << endl;
    722     return false;
    723   }
    724  
    725   AtomCounter = (int *) Malloc(sizeof(int)*FragmentCounter, "KeySetsContainer::ParseKeySets: *RowCounter");
    726   for(int i=0;(i<FragmentCounter) && (!input.eof());i++) {
    727     stringstream line;
    728     AtomCounter[i] = ACounter[i];
    729     // parse the values
    730     KeySets[i] = (int *) Malloc(sizeof(int)*AtomCounter[i], "KeySetsContainer::ParseKeySets: *KeySets[]");
    731     for(int j=AtomCounter[i];j--;)
    732       KeySets[i][j] = -1;
    733     FragmentNumber = FixedDigitNumber(FragmentCounter, i);
    734     //cout << FRAGMENTPREFIX << FragmentNumber << "[" << AtomCounter[i] << "]:";
    735     Free((void **)&FragmentNumber, "KeySetsContainer::ParseKeySets: *FragmentNumber");
    736     input.getline(filename, 1023);
    737     line.str(filename);
    738     for(int j=0;(j<AtomCounter[i]) && (!line.eof());j++) {
    739       line >> KeySets[i][j];
    740       //cout << " " << KeySets[i][j];
    741     }
    742     //cout << endl;
    743   }
    744   input.close();
    745   return true;
     708        ifstream input;
     709        char *FragmentNumber = NULL;
     710        stringstream file;
     711        char filename[1023];
     712
     713        FragmentCounter = FCounter;
     714        cout << "Parsing key sets." << endl;
     715        KeySets = (int **) Malloc(sizeof(int *)*FragmentCounter, "KeySetsContainer::ParseKeySets: **KeySets");
     716        for(int i=FragmentCounter;i--;)
     717                KeySets[i] = NULL;
     718        file << name << FRAGMENTPREFIX << KEYSETFILE;
     719        input.open(file.str().c_str(), ios::in);
     720        if (input == NULL) {
     721                cout << endl << "Unable to open " << file.str() << ", is the directory correct?" << endl;
     722                return false;
     723        }
     724
     725        AtomCounter = (int *) Malloc(sizeof(int)*FragmentCounter, "KeySetsContainer::ParseKeySets: *RowCounter");
     726        for(int i=0;(i<FragmentCounter) && (!input.eof());i++) {
     727                stringstream line;
     728                AtomCounter[i] = ACounter[i];
     729                // parse the values
     730                KeySets[i] = (int *) Malloc(sizeof(int)*AtomCounter[i], "KeySetsContainer::ParseKeySets: *KeySets[]");
     731                for(int j=AtomCounter[i];j--;)
     732                        KeySets[i][j] = -1;
     733                FragmentNumber = FixedDigitNumber(FragmentCounter, i);
     734                //cout << FRAGMENTPREFIX << FragmentNumber << "[" << AtomCounter[i] << "]:";
     735                Free((void **)&FragmentNumber, "KeySetsContainer::ParseKeySets: *FragmentNumber");
     736                input.getline(filename, 1023);
     737                line.str(filename);
     738                for(int j=0;(j<AtomCounter[i]) && (!line.eof());j++) {
     739                        line >> KeySets[i][j];
     740                        //cout << " " << KeySets[i][j];
     741                }
     742                //cout << endl;
     743        }
     744        input.close();
     745        return true;
    746746};
    747747
     
    751751bool KeySetsContainer::ParseManyBodyTerms()
    752752{
    753   int Counter;
    754  
    755   cout << "Creating Fragment terms." << endl;
    756   // scan through all to determine maximum order
    757   Order=0;
    758   for(int i=FragmentCounter;i--;) {
    759     Counter=0;
    760     for(int j=AtomCounter[i];j--;)
    761       if (KeySets[i][j] != -1)
    762         Counter++;
    763     if (Counter > Order)
    764       Order = Counter;
    765   }
    766   cout << "Found Order is " << Order << "." << endl;
    767  
    768   // scan through all to determine fragments per order
    769   FragmentsPerOrder = (int *) Malloc(sizeof(int)*Order, "KeySetsContainer::ParseManyBodyTerms: *FragmentsPerOrder");
    770   for(int i=Order;i--;)
    771     FragmentsPerOrder[i] = 0;
    772   for(int i=FragmentCounter;i--;) {
    773     Counter=0;
    774     for(int j=AtomCounter[i];j--;)
    775       if (KeySets[i][j] != -1)
    776         Counter++;
    777     FragmentsPerOrder[Counter-1]++;
    778   }
    779   for(int i=0;i<Order;i++)
    780     cout << "Found No. of Fragments of Order " << i+1 << " is " << FragmentsPerOrder[i] << "." << endl;
    781    
    782   // scan through all to gather indices to each order set
    783   OrderSet = (int **) Malloc(sizeof(int *)*Order, "KeySetsContainer::ParseManyBodyTerms: **OrderSet");
    784   for(int i=Order;i--;)
    785     OrderSet[i] = (int *) Malloc(sizeof(int)*FragmentsPerOrder[i], "KeySetsContainer::ParseManyBodyTermsKeySetsContainer::ParseManyBodyTerms: *OrderSet[]");
    786   for(int i=Order;i--;)
    787     FragmentsPerOrder[i] = 0;
    788   for(int i=FragmentCounter;i--;) {
    789     Counter=0;
    790     for(int j=AtomCounter[i];j--;)
    791       if (KeySets[i][j] != -1)
    792         Counter++;
    793     OrderSet[Counter-1][FragmentsPerOrder[Counter-1]] = i;
    794     FragmentsPerOrder[Counter-1]++;
    795   }
    796   cout << "Printing OrderSet." << endl;
    797   for(int i=0;i<Order;i++) {
    798     for (int j=0;j<FragmentsPerOrder[i];j++) {
    799       cout << " " << OrderSet[i][j];
    800     }
    801     cout << endl;
    802   }
    803   cout << endl;
    804  
    805    
    806   return true;
     753        int Counter;
     754
     755        cout << "Creating Fragment terms." << endl;
     756        // scan through all to determine maximum order
     757        Order=0;
     758        for(int i=FragmentCounter;i--;) {
     759                Counter=0;
     760                for(int j=AtomCounter[i];j--;)
     761                        if (KeySets[i][j] != -1)
     762                                Counter++;
     763                if (Counter > Order)
     764                        Order = Counter;
     765        }
     766        cout << "Found Order is " << Order << "." << endl;
     767
     768        // scan through all to determine fragments per order
     769        FragmentsPerOrder = (int *) Malloc(sizeof(int)*Order, "KeySetsContainer::ParseManyBodyTerms: *FragmentsPerOrder");
     770        for(int i=Order;i--;)
     771                FragmentsPerOrder[i] = 0;
     772        for(int i=FragmentCounter;i--;) {
     773                Counter=0;
     774                for(int j=AtomCounter[i];j--;)
     775                        if (KeySets[i][j] != -1)
     776                                Counter++;
     777                FragmentsPerOrder[Counter-1]++;
     778        }
     779        for(int i=0;i<Order;i++)
     780                cout << "Found No. of Fragments of Order " << i+1 << " is " << FragmentsPerOrder[i] << "." << endl;
     781
     782        // scan through all to gather indices to each order set
     783        OrderSet = (int **) Malloc(sizeof(int *)*Order, "KeySetsContainer::ParseManyBodyTerms: **OrderSet");
     784        for(int i=Order;i--;)
     785                OrderSet[i] = (int *) Malloc(sizeof(int)*FragmentsPerOrder[i], "KeySetsContainer::ParseManyBodyTermsKeySetsContainer::ParseManyBodyTerms: *OrderSet[]");
     786        for(int i=Order;i--;)
     787                FragmentsPerOrder[i] = 0;
     788        for(int i=FragmentCounter;i--;) {
     789                Counter=0;
     790                for(int j=AtomCounter[i];j--;)
     791                        if (KeySets[i][j] != -1)
     792                                Counter++;
     793                OrderSet[Counter-1][FragmentsPerOrder[Counter-1]] = i;
     794                FragmentsPerOrder[Counter-1]++;
     795        }
     796        cout << "Printing OrderSet." << endl;
     797        for(int i=0;i<Order;i++) {
     798                for (int j=0;j<FragmentsPerOrder[i];j++) {
     799                        cout << " " << OrderSet[i][j];
     800                }
     801                cout << endl;
     802        }
     803        cout << endl;
     804
     805
     806        return true;
    807807};
    808808
     
    814814bool KeySetsContainer::Contains(const int GreaterSet, const int SmallerSet)
    815815{
    816   bool result = true;
    817   bool intermediate;
    818   if ((GreaterSet < 0) || (SmallerSet < 0) || (GreaterSet > FragmentCounter) || (SmallerSet > FragmentCounter)) // index out of bounds
    819     return false;
    820   for(int i=AtomCounter[SmallerSet];i--;) {
    821     intermediate = false;
    822     for (int j=AtomCounter[GreaterSet];j--;)
    823       intermediate = (intermediate || ((KeySets[SmallerSet][i] == KeySets[GreaterSet][j]) || (KeySets[SmallerSet][i] == -1)));
    824     result = result && intermediate;
    825   }
    826 
    827   return result;
     816        bool result = true;
     817        bool intermediate;
     818        if ((GreaterSet < 0) || (SmallerSet < 0) || (GreaterSet > FragmentCounter) || (SmallerSet > FragmentCounter)) // index out of bounds
     819                return false;
     820        for(int i=AtomCounter[SmallerSet];i--;) {
     821                intermediate = false;
     822                for (int j=AtomCounter[GreaterSet];j--;)
     823                        intermediate = (intermediate || ((KeySets[SmallerSet][i] == KeySets[GreaterSet][j]) || (KeySets[SmallerSet][i] == -1)));
     824                result = result && intermediate;
     825        }
     826
     827        return result;
    828828};
    829829
  • src/parser.hpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    22 *
    33 * Definitions of various class functions for the parsing of value files.
    4  *   
     4 *
    55 */
    66
     
    4040
    4141class MatrixContainer {
    42   public:
    43     double ***Matrix;
    44     int **Indices;
    45     char *Header;
    46     int MatrixCounter;
    47     int *RowCounter;
    48     int ColumnCounter;
    49  
    50   MatrixContainer();
    51   ~MatrixContainer();
    52  
    53   bool ParseMatrix(const char *name, int skiplines, int skipcolumns, int MatrixNr);
    54   virtual bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns);
    55   bool AllocateMatrix(char *GivenHeader, int MCounter, int *RCounter, int CCounter);
    56   bool ResetMatrix();
    57   double FindMinValue();
    58   double FindMaxValue();
    59   bool SetLastMatrix(double value, int skipcolumns);
    60   bool SetLastMatrix(double **values, int skipcolumns);
    61   //bool ParseIndices();
    62   //bool SumSubValues();
    63   bool SumSubManyBodyTerms(class MatrixContainer &Matrix, class KeySetsContainer &KeySet, int Order);
    64   bool WriteTotalFragments(const char *name, const char *prefix);
    65   bool WriteLastMatrix(const char *name, const char *prefix, const char *suffix);
    66 }; 
     42        public:
     43                double ***Matrix;
     44                int **Indices;
     45                char *Header;
     46                int MatrixCounter;
     47                int *RowCounter;
     48                int ColumnCounter;
     49
     50        MatrixContainer();
     51        virtual ~MatrixContainer();
     52
     53        bool ParseMatrix(const char *name, int skiplines, int skipcolumns, int MatrixNr);
     54        virtual bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns);
     55        bool AllocateMatrix(char *GivenHeader, int MCounter, int *RCounter, int CCounter);
     56        bool ResetMatrix();
     57        double FindMinValue();
     58        double FindMaxValue();
     59        bool SetLastMatrix(double value, int skipcolumns);
     60        bool SetLastMatrix(double **values, int skipcolumns);
     61        //bool ParseIndices();
     62        //bool SumSubValues();
     63        bool SumSubManyBodyTerms(class MatrixContainer &Matrix, class KeySetsContainer &KeySet, int Order);
     64        bool WriteTotalFragments(const char *name, const char *prefix);
     65        bool WriteLastMatrix(const char *name, const char *prefix, const char *suffix);
     66};
    6767
    6868// ======================================= CLASS EnergyMatrix =============================
    6969
    7070class EnergyMatrix : public MatrixContainer {
    71   public:
    72     bool ParseIndices();
    73     bool SumSubEnergy(class EnergyMatrix &Fragments, class EnergyMatrix *CorrectionFragments, class KeySetsContainer &KeySet, int Order, double sign);
    74     bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns);
     71        public:
     72                bool ParseIndices();
     73                bool SumSubEnergy(class EnergyMatrix &Fragments, class EnergyMatrix *CorrectionFragments, class KeySetsContainer &KeySet, int Order, double sign);
     74                bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns);
    7575};
    7676
     
    7878
    7979class ForceMatrix : public MatrixContainer {
    80   public:
    81     bool ParseIndices(char *name);
    82     bool SumSubForces(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign);
    83     bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns);
     80        public:
     81                bool ParseIndices(char *name);
     82                bool SumSubForces(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign);
     83                bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns);
    8484};
    8585
     
    8787
    8888class KeySetsContainer {
    89   public:
    90     int **KeySets;
    91     int *AtomCounter;
    92     int FragmentCounter;
    93     int Order;
    94     int *FragmentsPerOrder;
    95     int **OrderSet;
    96  
    97   KeySetsContainer();
    98   ~KeySetsContainer();
    99    
    100   bool ParseKeySets(const char *name, const int *ACounter, const int FCounter);
    101   bool ParseManyBodyTerms();
    102   bool Contains(const int GreaterSet, const int SmallerSet);
     89        public:
     90                int **KeySets;
     91                int *AtomCounter;
     92                int FragmentCounter;
     93                int Order;
     94                int *FragmentsPerOrder;
     95                int **OrderSet;
     96
     97        KeySetsContainer();
     98        ~KeySetsContainer();
     99
     100        bool ParseKeySets(const char *name, const int *ACounter, const int FCounter);
     101        bool ParseManyBodyTerms();
     102        bool Contains(const int GreaterSet, const int SmallerSet);
    103103};
    104104
  • src/periodentafel.cpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    11/** \file periodentafel.cpp
    2  * 
     2 *
    33 * Function implementations for the class periodentafel.
    4  * 
     4 *
    55 */
    66
     
    1414 * Initialises start and end of list and resets periodentafel::checkliste to false.
    1515 */
    16 periodentafel::periodentafel() 
    17 { 
    18   start = new element;
    19   end = new element;
    20   start->previous = NULL;
    21   start->next = end;
    22   end->previous = start;
    23   end->next = NULL;
     16periodentafel::periodentafel()
     17{
     18        start = new element;
     19        end = new element;
     20        start->previous = NULL;
     21        start->next = end;
     22        end->previous = start;
     23        end->next = NULL;
    2424};
    2525
     
    2727 * Removes every element and afterwards deletes start and end of list.
    2828 */
    29 periodentafel::~periodentafel() 
    30 { 
    31   CleanupPeriodtable();
    32   delete(end);
    33   delete(start);
    34 }; 
     29periodentafel::~periodentafel()
     30{
     31        CleanupPeriodtable();
     32        delete(end);
     33        delete(start);
     34};
    3535
    3636/** Adds element to period table list
     
    3838 * \return true - succeeded, false - does not occur
    3939 */
    40 bool periodentafel::AddElement(element *pointer) 
    41 { 
    42   pointer->sort = &pointer->Z;
    43   if (pointer->Z < 1 && pointer->Z >= MAX_ELEMENTS)
    44     cout << Verbose(0) << "Invalid Z number!\n";
    45   return add(pointer, end);
     40bool periodentafel::AddElement(element *pointer)
     41{
     42        pointer->sort = &pointer->Z;
     43        if (pointer->Z < 1 && pointer->Z >= MAX_ELEMENTS)
     44                cout << Verbose(0) << "Invalid Z number!\n";
     45        return add(pointer, end);
    4646};
    4747
     
    5050 * \return true - succeeded, false - element not found
    5151 */
    52 bool periodentafel::RemoveElement(element *pointer) 
    53 { 
    54   return remove(pointer, start, end);
     52bool periodentafel::RemoveElement(element *pointer)
     53{
     54        return remove(pointer, start, end);
    5555};
    5656
     
    5858 * \return true - succeeded, false - does not occur
    5959 */
    60 bool periodentafel::CleanupPeriodtable() 
    61 { 
    62   return cleanup(start,end);
     60bool periodentafel::CleanupPeriodtable()
     61{
     62        return cleanup(start,end);
    6363};
    6464
     
    7070element * periodentafel::FindElement(int Z)
    7171{
    72   element *walker = find(&Z, start,end);
    73   if (walker == NULL) { // not found: enter and put into db
    74     cout << Verbose(0) << "Element not found in database, please enter." << endl;
    75     walker = new element;
    76     cout << Verbose(0) << "Mass: " << endl;
    77     cin >> walker->mass;
    78     walker->Z = Z; 
    79     cout << Verbose(0) << "Atomic number: " << walker->Z << endl; 
    80     cout << Verbose(0) << "Name [max 64 chars]: " << endl;
    81     cin >> walker->name;
    82     cout << Verbose(0) << "Short form [max 3 chars]: " << endl;
    83     cin >> walker->symbol;
    84     periodentafel::AddElement(walker);
    85   }
    86   return(walker);
     72        element *walker = find(&Z, start,end);
     73        if (walker == NULL) { // not found: enter and put into db
     74                cout << Verbose(0) << "Element not found in database, please enter." << endl;
     75                walker = new element;
     76                cout << Verbose(0) << "Mass: " << endl;
     77                cin >> walker->mass;
     78                walker->Z = Z;
     79                cout << Verbose(0) << "Atomic number: " << walker->Z << endl;
     80                cout << Verbose(0) << "Name [max 64 chars]: " << endl;
     81                cin >> walker->name;
     82                cout << Verbose(0) << "Short form [max 3 chars]: " << endl;
     83                cin >> walker->symbol;
     84                periodentafel::AddElement(walker);
     85        }
     86        return(walker);
    8787};
    8888
     
    9494element * periodentafel::FindElement(char *shorthand) const
    9595{
    96   element *walker =  periodentafel::start;
    97   while (walker->next != periodentafel::end) {
    98     walker = walker->next;
    99     if (strncmp(walker->symbol, shorthand, 3) == 0)
    100       return(walker);
    101   }
    102   return (NULL);
     96        element *walker =       periodentafel::start;
     97        while (walker->next != periodentafel::end) {
     98                walker = walker->next;
     99                if (strncmp(walker->symbol, shorthand, 3) == 0)
     100                        return(walker);
     101        }
     102        return (NULL);
    103103};
    104104
    105105/** Asks for element number and returns pointer to element
    106106 */
    107 element * periodentafel::AskElement()
    108 {
    109   element *walker = NULL;
    110   int Z;
    111   do {
    112     cout << Verbose(0) << "Atomic number Z: ";
    113     cin >> Z;
    114     walker = this->FindElement(Z);  // give type
    115   } while (walker == NULL);
    116   return walker;
    117 };
    118 
     107element * periodentafel::AskElement()
     108{
     109        element *walker = NULL;
     110        int Z;
     111        do {
     112                cout << Verbose(0) << "Atomic number Z: ";
     113                cin >> Z;
     114                walker = this->FindElement(Z);  // give type
     115        } while (walker == NULL);
     116        return walker;
     117};
    119118
    120119/** Prints period table to given stream.
    121120 * \param output stream
    122  */ 
     121 */
    123122bool periodentafel::Output(ofstream *output) const
    124123{
    125   bool result = true;
    126   element *walker = start;
    127   if (output != NULL) {
    128     while (walker->next != end) {
    129       walker = walker->next;
    130       result = result && walker->Output(output);
    131     }
    132     return result;
    133   } else
    134     return false;
     124        bool result = true;
     125        element *walker = start;
     126        if (output != NULL) {
     127                while (walker->next != end) {
     128                        walker = walker->next;
     129                        result = result && walker->Output(output);
     130                }
     131                return result;
     132        } else
     133                return false;
    135134};
    136135
     
    138137 * \param *output output stream
    139138 * \param *checkliste elements table for this molecule
    140  */ 
     139 */
    141140bool periodentafel::Checkout(ofstream *output, const int *checkliste) const
    142141{
    143   element *walker = start;
    144   bool result = true;
    145   int No = 1;
    146 
    147   if (output != NULL) {
    148     *output << "# Ion type data (PP = PseudoPotential, Z = atomic number)" << endl;
    149     *output << "#Ion_TypeNr.\tAmount\tZ\tRGauss\tL_Max(PP)L_Loc(PP)IonMass\t# chemical name, symbol" << endl;
    150     while (walker->next != end) {
    151       walker = walker->next;
    152       if ((walker != NULL) && (walker->Z > 0) && (walker->Z < MAX_ELEMENTS) && (checkliste[walker->Z])) {
    153         walker->No = No;
    154         result = result && walker->Checkout(output, No++, checkliste[walker->Z]);     
    155       }
    156     }
    157     return result;
    158   } else
    159     return false;
    160 };
    161 
     142        element *walker = start;
     143        bool result = true;
     144        int No = 1;
     145
     146        if (output != NULL) {
     147                *output << "# Ion type data (PP = PseudoPotential, Z = atomic number)" << endl;
     148                *output << "#Ion_TypeNr.\tAmount\tZ\tRGauss\tL_Max(PP)L_Loc(PP)IonMass\t# chemical name, symbol" << endl;
     149                while (walker->next != end) {
     150                        walker = walker->next;
     151                        if ((walker != NULL) && (walker->Z > 0) && (walker->Z < MAX_ELEMENTS) && (checkliste[walker->Z])) {
     152                                walker->No = No;
     153                                result = result && walker->Checkout(output, No++, checkliste[walker->Z]);
     154                        }
     155                }
     156                return result;
     157        } else
     158                return false;
     159};
    162160
    163161/** Loads element list from file.
     
    166164bool periodentafel::LoadPeriodentafel(char *path)
    167165{
    168   ifstream infile;
    169   double tmp;
    170   element *ptr;
    171   bool status = true;
    172   bool otherstatus = true;
    173   char *filename = new char[MAXSTRINGSIZE];
    174  
    175   // fill elements DB
    176   strncpy(filename, path, MAXSTRINGSIZE);
    177   strncat(filename, "/", MAXSTRINGSIZE-strlen(filename));
    178   strncat(filename, STANDARDELEMENTSDB, MAXSTRINGSIZE-strlen(filename));
    179   infile.open(filename);
    180   if (infile != NULL) {
    181     infile.getline(header1, MAXSTRINGSIZE);
    182     infile.getline(header2, MAXSTRINGSIZE); // skip first two header lines
    183     cout <<  "Parsed elements:";
    184     while (!infile.eof()) {
    185       element *neues = new element;
    186       infile >> neues->name;
    187       //infile >> ws;
    188       infile >> neues->symbol;
    189       //infile >> ws;
    190       infile >> neues->period;
    191       //infile >> ws;
    192       infile >> neues->group;
    193       //infile >> ws;
    194       infile >> neues->block;
    195       //infile >> ws;
    196       infile >> neues->Z;
    197       //infile >> ws;
    198       infile >> neues->mass;
    199       //infile >> ws;
    200       infile >> neues->CovalentRadius;
    201       //infile >> ws;
    202       infile >> neues->VanDerWaalsRadius;
    203       //infile >> ws;
    204       infile >> ws;
    205       cout << " " << neues->symbol;
    206       //neues->Output((ofstream *)&cout);
    207       if ((neues->Z > 0) && (neues->Z < MAX_ELEMENTS))
    208         periodentafel::AddElement(neues);
    209       else {
    210         cout << "Could not parse element: ";
    211         neues->Output((ofstream *)&cout);
    212       }
    213     }
    214     cout << endl;
    215     infile.close();
    216     infile.clear();
    217   } else
    218     status = false;
    219 
    220   // fill valence DB per element
    221   strncpy(filename, path, MAXSTRINGSIZE);
    222   strncat(filename, "/", MAXSTRINGSIZE-strlen(filename));
    223   strncat(filename, STANDARDVALENCEDB, MAXSTRINGSIZE-strlen(filename));
    224   infile.open(filename);
    225   if (infile != NULL) {
    226     while (!infile.eof()) {
    227         infile >> tmp;
    228         infile >> ws;
    229         infile >> FindElement((int)tmp)->Valence;
    230         infile >> ws;
    231         //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->Valence << " valence electrons." << endl;
    232     }
    233     infile.close();
    234     infile.clear();
    235   } else
    236     otherstatus = false;
    237 
    238   // fill valence DB per element
    239   strncpy(filename, path, MAXSTRINGSIZE);
    240   strncat(filename, "/", MAXSTRINGSIZE-strlen(filename));
    241   strncat(filename, STANDARDORBITALDB, MAXSTRINGSIZE-strlen(filename));
    242   infile.open(filename);
    243   if (infile != NULL) {
    244     while (!infile.eof()) {
    245       infile >> tmp;
    246       infile >> ws;
    247       infile >> FindElement((int)tmp)->NoValenceOrbitals;
    248       infile >> ws;
    249       //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->NoValenceOrbitals << " number of singly occupied valence orbitals." << endl;
    250     }
    251     infile.close();
    252     infile.clear();
    253   } else
    254     otherstatus = false;
    255  
    256   // fill H-BondDistance DB per element
    257   strncpy(filename, path, MAXSTRINGSIZE);
    258   strncat(filename, "/", MAXSTRINGSIZE-strlen(filename));
    259   strncat(filename, STANDARDHBONDDISTANCEDB, MAXSTRINGSIZE-strlen(filename));
    260   infile.open(filename);
    261   if (infile != NULL) {
    262     while (!infile.eof()) {
    263         infile >> tmp;
    264       ptr = FindElement((int)tmp);
    265         infile >> ws;
    266       infile >> ptr->HBondDistance[0];
    267       infile >> ptr->HBondDistance[1];
    268       infile >> ptr->HBondDistance[2];
    269         infile >> ws;
    270       //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->HBondDistance[0] << " Angstrom typical distance to hydrogen." << endl;
    271     }
    272     infile.close();
    273     infile.clear();
    274   } else
    275     otherstatus = false;
    276  
    277   // fill H-BondAngle DB per element
    278   strncpy(filename, path, MAXSTRINGSIZE);
    279   strncat(filename, "/", MAXSTRINGSIZE-strlen(filename));
    280   strncat(filename, STANDARDHBONDANGLEDB, MAXSTRINGSIZE-strlen(filename));
    281   infile.open(filename);
    282   if (infile != NULL) {
    283     while (!infile.eof()) {
    284       infile >> tmp;
    285       ptr = FindElement((int)tmp);
    286       infile >> ws;
    287       infile >> ptr->HBondAngle[0];
    288       infile >> ptr->HBondAngle[1];
    289       infile >> ptr->HBondAngle[2];
    290       infile >> ws;
    291       //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->HBondAngle[0] << ", " << FindElement((int)tmp)->HBondAngle[1] << ", " << FindElement((int)tmp)->HBondAngle[2] << " degrees bond angle for one, two, three connected hydrogens." << endl;
    292     }
    293     infile.close();
    294   } else
    295     otherstatus = false;
    296  
    297   if (!otherstatus)
    298     cerr << "WARNING: Something went wrong while parsing the other databases!" << endl;
    299  
    300   return status;
     166        ifstream infile;
     167        double tmp;
     168        element *ptr;
     169        bool status = true;
     170        bool otherstatus = true;
     171        char filename[255];
     172
     173        // fill elements DB
     174        strncpy(filename, path, MAXSTRINGSIZE);
     175        strncat(filename, "/", MAXSTRINGSIZE-strlen(filename));
     176        strncat(filename, STANDARDELEMENTSDB, MAXSTRINGSIZE-strlen(filename));
     177        infile.open(filename);
     178        if (infile != NULL) {
     179                infile.getline(header1, MAXSTRINGSIZE);
     180                infile.getline(header2, MAXSTRINGSIZE); // skip first two header lines
     181                cout << "Parsed elements:";
     182                while (!infile.eof()) {
     183                        element *neues = new element;
     184                        infile >> neues->name;
     185                        //infile >> ws;
     186                        infile >> neues->symbol;
     187                        //infile >> ws;
     188                        infile >> neues->period;
     189                        //infile >> ws;
     190                        infile >> neues->group;
     191                        //infile >> ws;
     192                        infile >> neues->block;
     193                        //infile >> ws;
     194                        infile >> neues->Z;
     195                        //infile >> ws;
     196                        infile >> neues->mass;
     197                        //infile >> ws;
     198                        infile >> neues->CovalentRadius;
     199                        //infile >> ws;
     200                        infile >> neues->VanDerWaalsRadius;
     201                        //infile >> ws;
     202                        infile >> ws;
     203                        cout << " " << neues->symbol;
     204                        //neues->Output((ofstream *)&cout);
     205                        if ((neues->Z > 0) && (neues->Z < MAX_ELEMENTS))
     206                                periodentafel::AddElement(neues);
     207                        else {
     208                                cout << "Could not parse element: ";
     209                                neues->Output((ofstream *)&cout);
     210                        }
     211                }
     212                cout << endl;
     213                infile.close();
     214                infile.clear();
     215        } else
     216                status = false;
     217
     218        // fill valence DB per element
     219        strncpy(filename, path, MAXSTRINGSIZE);
     220        strncat(filename, "/", MAXSTRINGSIZE-strlen(filename));
     221        strncat(filename, STANDARDVALENCEDB, MAXSTRINGSIZE-strlen(filename));
     222        infile.open(filename);
     223        if (infile != NULL) {
     224                while (!infile.eof()) {
     225                        infile >> tmp;
     226                        infile >> ws;
     227                        infile >> FindElement((int)tmp)->Valence;
     228                        infile >> ws;
     229                        //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->Valence << " valence electrons." << endl;
     230                }
     231                infile.close();
     232                infile.clear();
     233        } else
     234                otherstatus = false;
     235
     236        // fill valence DB per element
     237        strncpy(filename, path, MAXSTRINGSIZE);
     238        strncat(filename, "/", MAXSTRINGSIZE-strlen(filename));
     239        strncat(filename, STANDARDORBITALDB, MAXSTRINGSIZE-strlen(filename));
     240        infile.open(filename);
     241        if (infile != NULL) {
     242                while (!infile.eof()) {
     243                        infile >> tmp;
     244                        infile >> ws;
     245                        infile >> FindElement((int)tmp)->NoValenceOrbitals;
     246                        infile >> ws;
     247                        //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->NoValenceOrbitals << " number of singly occupied valence orbitals." << endl;
     248                }
     249                infile.close();
     250                infile.clear();
     251        } else
     252                otherstatus = false;
     253
     254        // fill H-BondDistance DB per element
     255        strncpy(filename, path, MAXSTRINGSIZE);
     256        strncat(filename, "/", MAXSTRINGSIZE-strlen(filename));
     257        strncat(filename, STANDARDHBONDDISTANCEDB, MAXSTRINGSIZE-strlen(filename));
     258        infile.open(filename);
     259        if (infile != NULL) {
     260                while (!infile.eof()) {
     261                        infile >> tmp;
     262                        ptr = FindElement((int)tmp);
     263                        infile >> ws;
     264                        infile >> ptr->HBondDistance[0];
     265                        infile >> ptr->HBondDistance[1];
     266                        infile >> ptr->HBondDistance[2];
     267                        infile >> ws;
     268                        //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->HBondDistance[0] << " Angstrom typical distance to hydrogen." << endl;
     269                }
     270                infile.close();
     271                infile.clear();
     272        } else
     273                otherstatus = false;
     274
     275        // fill H-BondAngle DB per element
     276        strncpy(filename, path, MAXSTRINGSIZE);
     277        strncat(filename, "/", MAXSTRINGSIZE-strlen(filename));
     278        strncat(filename, STANDARDHBONDANGLEDB, MAXSTRINGSIZE-strlen(filename));
     279        infile.open(filename);
     280        if (infile != NULL) {
     281                while (!infile.eof()) {
     282                        infile >> tmp;
     283                        ptr = FindElement((int)tmp);
     284                        infile >> ws;
     285                        infile >> ptr->HBondAngle[0];
     286                        infile >> ptr->HBondAngle[1];
     287                        infile >> ptr->HBondAngle[2];
     288                        infile >> ws;
     289                        //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->HBondAngle[0] << ", " << FindElement((int)tmp)->HBondAngle[1] << ", " << FindElement((int)tmp)->HBondAngle[2] << " degrees bond angle for one, two, three connected hydrogens." << endl;
     290                }
     291                infile.close();
     292        } else
     293                otherstatus = false;
     294
     295        if (!otherstatus)
     296                cerr << "WARNING: Something went wrong while parsing the other databases!" << endl;
     297
     298        return status;
    301299};
    302300
     
    305303bool periodentafel::StorePeriodentafel(char *path) const
    306304{
    307   bool result = true;
    308   ofstream f;
    309   char filename[MAXSTRINGSIZE];
    310  
    311   strncpy(filename, path, MAXSTRINGSIZE);
    312   strncat(filename, "/", MAXSTRINGSIZE-strlen(filename));
    313   strncat(filename, STANDARDELEMENTSDB, MAXSTRINGSIZE-strlen(filename));
    314   f.open(filename);
    315   if (f != NULL) {
    316     f << header1 << endl;
    317     f << header2 << endl;
    318     element *walker = periodentafel::start;
    319     while (walker->next != periodentafel::end) {
    320       walker = walker->next;
    321       result = result && walker->Output(&f);
    322     }
    323     f.close();
    324   } else
    325     result = false;
    326   return result;
    327 };
     305        bool result = true;
     306        ofstream f;
     307        char filename[MAXSTRINGSIZE];
     308
     309        strncpy(filename, path, MAXSTRINGSIZE);
     310        strncat(filename, "/", MAXSTRINGSIZE-strlen(filename));
     311        strncat(filename, STANDARDELEMENTSDB, MAXSTRINGSIZE-strlen(filename));
     312        f.open(filename);
     313        if (f != NULL) {
     314                f << header1 << endl;
     315                f << header2 << endl;
     316                element *walker = periodentafel::start;
     317                while (walker->next != periodentafel::end) {
     318                        walker = walker->next;
     319                        result = result && walker->Output(&f);
     320                }
     321                f.close();
     322        } else
     323                result = false;
     324        return result;
     325};
  • src/periodentafel.hpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    2121 */
    2222class element {
    23   public:
    24     double mass;    //!< mass in g/mol
    25     double CovalentRadius;  //!< covalent radius
    26     double VanDerWaalsRadius;  //!< can-der-Waals radius
    27     int Z;          //!< atomic number
    28     char name[64];  //!< atom name, i.e. "Hydrogren"
    29     char symbol[3]; //!< short form of the atom, i.e. "H"
    30     char period[8];    //!< period: n quantum number
    31     char group[8];    //!< group: l quantum number
    32     char block[8];    //!< block: l quantum number
    33     element *previous;  //!< previous item in list
    34     element *next;  //!< next element in list
    35     int *sort;      //!< sorc criteria
    36     int No;        //!< number of element set on periodentafel::Output()
    37     double Valence;  //!< number of valence electrons for this element
    38     int NoValenceOrbitals;  //!< number of valence orbitals, used for determining bond degree in molecule::CreateConnectmatrix()
    39     double HBondDistance[NDIM]; //!< distance in Angstrom of this element to hydrogen  (for single, double and triple bonds)
    40     double HBondAngle[NDIM];    //!< typical angle for one, two, three bonded hydrogen (in degrees)
     23        public:
     24                double mass;            //!< mass in g/mol
     25                double CovalentRadius;  //!< covalent radius
     26                double VanDerWaalsRadius;       //!< can-der-Waals radius
     27                int Z;                                  //!< atomic number
     28                char name[64];  //!< atom name, i.e. "Hydrogren"
     29                char symbol[3]; //!< short form of the atom, i.e. "H"
     30                char period[8];         //!< period: n quantum number
     31                char group[8];          //!< group: l quantum number
     32                char block[8];          //!< block: l quantum number
     33                element *previous;      //!< previous item in list
     34                element *next;  //!< next element in list
     35                int *sort;                      //!< sorc criteria
     36                int No;                          //!< number of element set on periodentafel::Output()
     37                double Valence; //!< number of valence electrons for this element
     38                int NoValenceOrbitals;  //!< number of valence orbitals, used for determining bond degree in molecule::CreateConnectmatrix()
     39                double HBondDistance[NDIM]; //!< distance in Angstrom of this element to hydrogen       (for single, double and triple bonds)
     40                double HBondAngle[NDIM];                //!< typical angle for one, two, three bonded hydrogen (in degrees)
    4141
    42   element();
    43   ~element();
     42        element();
     43        ~element();
    4444
    45   //> print element entries to screen
    46   bool Output(ofstream *out) const;
    47   bool Checkout(ofstream *out, const int No, const int NoOfAtoms) const;
    48  
    49   private:
     45        //> print element entries to screen
     46        bool Output(ofstream *out) const;
     47        bool Checkout(ofstream *out, const int No, const int NoOfAtoms) const;
     48
     49        private:
    5050};
    5151
     
    5353 */
    5454class periodentafel {
    55   public:
    56     element *start; //!< start of element list
    57     element *end;  //!< end of element list
    58     char header1[MAXSTRINGSIZE]; //!< store first header line
    59     char header2[MAXSTRINGSIZE]; //!< store second header line
    60  
    61   periodentafel();
    62   ~periodentafel();
    63  
    64   bool AddElement(element *pointer);
    65   bool RemoveElement(element *pointer);
    66   bool CleanupPeriodtable();
    67   element * FindElement(int Z);
    68   element * FindElement(char *shorthand) const;
    69   element * AskElement();
    70   bool Output(ofstream *output) const;
    71   bool Checkout(ofstream *output, const int *checkliste) const;
    72   bool LoadPeriodentafel(char *path = NULL);
    73   bool StorePeriodentafel(char *path = NULL) const;
    74  
    75   private:
     55        public:
     56                element *start; //!< start of element list
     57                element *end;    //!< end of element list
     58                char header1[MAXSTRINGSIZE]; //!< store first header line
     59                char header2[MAXSTRINGSIZE]; //!< store second header line
     60
     61        periodentafel();
     62        ~periodentafel();
     63
     64        bool AddElement(element *pointer);
     65        bool RemoveElement(element *pointer);
     66        bool CleanupPeriodtable();
     67        element * FindElement(int Z);
     68        element * FindElement(char *shorthand) const;
     69        element * AskElement();
     70        bool Output(ofstream *output) const;
     71        bool Checkout(ofstream *output, const int *checkliste) const;
     72        bool LoadPeriodentafel(char *path = NULL);
     73        bool StorePeriodentafel(char *path = NULL) const;
     74
     75        private:
    7676};
    7777
  • src/stackclass.hpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    1010 */
    1111template <typename T> class StackClass {
    12   public:
    13   StackClass<T>(int dimension);
    14   ~StackClass<T>();
    15  
    16   bool Push(T object);
    17   T PopFirst();
    18   T PopLast();
    19   bool RemoveItem(T ptr);
    20   void ClearStack();
    21   bool IsEmpty();
    22   bool IsFull();
    23   int ItemCount();
    24   void Output(ofstream *out) const;
    25   void TestImplementation(ofstream *out, T test);
    26  
    27   private:
    28     T *StackList;  //!< the list containing the atom pointers
    29     int EntryCount;    //!< number of entries in the stack
    30     int CurrentLastEntry;  //!< Current last entry (newest item on stack)
    31     int CurrentFirstEntry;  //!< Current first entry (oldest item on stack)
    32     int NextFreeField;      //!< Current index of next free field
     12        public:
     13        StackClass<T>(int dimension);
     14        ~StackClass<T>();
     15
     16        bool Push(T object);
     17        T PopFirst();
     18        T PopLast();
     19        bool RemoveItem(T ptr);
     20        void ClearStack();
     21        bool IsEmpty();
     22        bool IsFull();
     23        int ItemCount();
     24        void Output(ofstream *out) const;
     25        void TestImplementation(ofstream *out, T test);
     26
     27        private:
     28                T *StackList;    //!< the list containing the atom pointers
     29                int EntryCount;          //!< number of entries in the stack
     30                int CurrentLastEntry;    //!< Current last entry (newest item on stack)
     31                int CurrentFirstEntry;  //!< Current first entry (oldest item on stack)
     32                int NextFreeField;                      //!< Current index of next free field
    3333};
    3434
     
    3737template <typename T> StackClass<T>::StackClass(int dimension)
    3838{
    39   CurrentLastEntry = 0;
    40   CurrentFirstEntry = 0;
    41   NextFreeField = 0;
    42   EntryCount = dimension;
    43   StackList = (T *) Malloc(sizeof(T)*EntryCount, "StackClass::StackClass: **StackList");
     39        CurrentLastEntry = 0;
     40        CurrentFirstEntry = 0;
     41        NextFreeField = 0;
     42        EntryCount = dimension;
     43        StackList = (T *) Malloc(sizeof(T)*EntryCount, "StackClass::StackClass: **StackList");
    4444};
    4545
     
    4848template <typename T> StackClass<T>::~StackClass()
    4949{
    50   Free((void **)&StackList, "StackClass::StackClass: **StackList");
     50        Free((void **)&StackList, "StackClass::StackClass: **StackList");
    5151};
    5252
     
    5757template <typename T> bool StackClass<T>::Push(T object)
    5858{
    59   if (!IsFull()) {    // check whether free field is really not occupied
    60     StackList[NextFreeField] = object;
    61     CurrentLastEntry = NextFreeField;
    62     NextFreeField = (NextFreeField + 1) % EntryCount; // step on to next free field
    63     return true;
    64   } else {
    65     cerr << "ERROR: Stack is full, " << "Stack: CurrentLastEntry " << CurrentLastEntry<< "\tCurrentFirstEntry " << CurrentFirstEntry << "\tNextFreeField " << NextFreeField << "\tEntryCount " << EntryCount << "!" << endl;
    66     return false;
    67   }
     59        if (!IsFull()) {                // check whether free field is really not occupied
     60                StackList[NextFreeField] = object;
     61                CurrentLastEntry = NextFreeField;
     62                NextFreeField = (NextFreeField + 1) % EntryCount; // step on to next free field
     63                return true;
     64        } else {
     65                cerr << "ERROR: Stack is full, " << "Stack: CurrentLastEntry " << CurrentLastEntry<< "\tCurrentFirstEntry " << CurrentFirstEntry << "\tNextFreeField " << NextFreeField << "\tEntryCount " << EntryCount << "!" << endl;
     66                return false;
     67        }
    6868};
    6969
     
    7474template <typename T> T StackClass<T>::PopFirst()
    7575{
    76   T Walker = NULL;
    77   if (!IsEmpty()) {
    78     Walker = StackList[CurrentFirstEntry];
    79     if (Walker == NULL)
    80       cerr << "ERROR: Stack's field is empty!" << endl;
    81     StackList[CurrentFirstEntry] = NULL;
    82     if (CurrentFirstEntry != CurrentLastEntry) { // hasn't last item been popped as well?
    83       CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1)
    84     } else {
    85       CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1)
    86       CurrentLastEntry = CurrentFirstEntry;
    87     }
    88   } else
    89     cerr << "ERROR: Stack is empty!" << endl;
    90   return Walker;
     76        T Walker = NULL;
     77        if (!IsEmpty()) {
     78                Walker = StackList[CurrentFirstEntry];
     79                if (Walker == NULL)
     80                        cerr << "ERROR: Stack's field is empty!" << endl;
     81                StackList[CurrentFirstEntry] = NULL;
     82                if (CurrentFirstEntry != CurrentLastEntry) { // hasn't last item been popped as well?
     83                        CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1)
     84                } else {
     85                        CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1)
     86                        CurrentLastEntry = CurrentFirstEntry;
     87                }
     88        } else
     89                cerr << "ERROR: Stack is empty!" << endl;
     90        return Walker;
    9191};
    9292
     
    9797template <typename T> T StackClass<T>::PopLast()
    9898{
    99   T Walker = NULL;
    100   if (!IsEmpty()) {
    101     Walker = StackList[CurrentLastEntry];
    102     StackList[CurrentLastEntry] = NULL;
    103     if (Walker == NULL)
    104       cerr << "ERROR: Stack's field is empty!" << endl;
    105     NextFreeField = CurrentLastEntry;
    106     if (CurrentLastEntry != CurrentFirstEntry)  // has there been more than one item on stack
    107       CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount; // step back from current free field to last (modulo does not work in -1, thus go EntryCount-1 instead)
    108   } else {
    109     cerr << "ERROR: Stack is empty!" << endl;
    110   }
    111   return Walker;
     99        T Walker = NULL;
     100        if (!IsEmpty()) {
     101                Walker = StackList[CurrentLastEntry];
     102                StackList[CurrentLastEntry] = NULL;
     103                if (Walker == NULL)
     104                        cerr << "ERROR: Stack's field is empty!" << endl;
     105                NextFreeField = CurrentLastEntry;
     106                if (CurrentLastEntry != CurrentFirstEntry)      // has there been more than one item on stack
     107                        CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount; // step back from current free field to last (modulo does not work in -1, thus go EntryCount-1 instead)
     108        } else {
     109                cerr << "ERROR: Stack is empty!" << endl;
     110        }
     111        return Walker;
    112112};
    113113
     
    120120template <typename T> bool StackClass<T>::RemoveItem(T ptr)
    121121{
    122   bool found = false;
    123   cout << Verbose(5) << "First " << CurrentFirstEntry<< "\tLast " << CurrentLastEntry<< "\tNext " << NextFreeField<< "\tCount " << EntryCount<< "." << endl;
    124   int i=CurrentFirstEntry;
    125   if (!IsEmpty())
    126     do {
    127       if (StackList[i] == ptr) {  // if item found, remove
    128         cout << Verbose(5) << "Item " << *ptr << " was number " << i << " on stack, removing it." << endl;
    129         found = true;
    130         StackList[i] = NULL;
    131       }
    132       if ((found) && (StackList[i] != NULL)) {  // means we have to shift (and not the removed item)
    133         if (i == 0) { // we are down to first item in stack, have to put onto last item
    134           cout << Verbose(5) << "Shifting item 0 to place " << EntryCount-1 << "." << endl;
    135           StackList[EntryCount-1] = StackList[0];
    136         } else {
    137           cout << Verbose(5) << "Shifting item " << i << " to place " << i-1 << "." << endl;
    138           StackList[i-1] = StackList[i];
    139         }
    140       }
    141       i=((i + 1) % EntryCount); // step on
    142     } while (i!=NextFreeField);
    143   else
    144     cerr << "ERROR: Stack is already empty!" << endl;
    145   if (found) {
    146     NextFreeField = CurrentLastEntry;
    147     if (CurrentLastEntry != CurrentFirstEntry)  // has there been more than one item on stack
    148       CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount;
    149   }
    150   return found;
     122        bool found = false;
     123        cout << Verbose(5) << "First " << CurrentFirstEntry<< "\tLast " << CurrentLastEntry<< "\tNext " << NextFreeField<< "\tCount " << EntryCount<< "." << endl;
     124        int i=CurrentFirstEntry;
     125        if (!IsEmpty())
     126                do {
     127                        if (StackList[i] == ptr) {      // if item found, remove
     128                                cout << Verbose(5) << "Item " << *ptr << " was number " << i << " on stack, removing it." << endl;
     129                                found = true;
     130                                StackList[i] = NULL;
     131                        }
     132                        if ((found) && (StackList[i] != NULL)) {        // means we have to shift (and not the removed item)
     133                                if (i == 0) { // we are down to first item in stack, have to put onto last item
     134                                        cout << Verbose(5) << "Shifting item 0 to place " << EntryCount-1 << "." << endl;
     135                                        StackList[EntryCount-1] = StackList[0];
     136                                } else {
     137                                        cout << Verbose(5) << "Shifting item " << i << " to place " << i-1 << "." << endl;
     138                                        StackList[i-1] = StackList[i];
     139                                }
     140                        }
     141                        i=((i + 1) % EntryCount); // step on
     142                } while (i!=NextFreeField);
     143        else
     144                cerr << "ERROR: Stack is already empty!" << endl;
     145        if (found) {
     146                NextFreeField = CurrentLastEntry;
     147                if (CurrentLastEntry != CurrentFirstEntry)      // has there been more than one item on stack
     148                        CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount;
     149        }
     150        return found;
    151151};
    152152
    153153/** Test the functionality of the stack.
    154154 * \param *out ofstream for debugging
    155  * \param *test one item to put on stack 
     155 * \param *test one item to put on stack
    156156 * \return true - all tests worked correctly
    157157 */
    158158template <typename T> void StackClass<T>::TestImplementation(ofstream *out, T test)
    159159{
    160   T Walker = test;
    161   *out << Verbose(1) << "Testing the snake stack..." << endl;
    162   for (int i=0;i<EntryCount;i++) {
    163     *out << Verbose(2) << "Filling " << i << "th element of stack." << endl;
    164     Push(Walker);
    165     Walker=Walker->next;
    166   }
    167   *out << endl;
    168   Output(out);
    169   if (IsFull())
    170     *out << "Stack is full as supposed to be!" << endl;
    171   else
    172     *out << "ERROR: Stack is not as full as supposed to be!" << endl;
    173   //if (StackList[(EntryCount+1)/2] != NULL) {
    174     *out << "Removing element in the middle ..." << endl;
    175     RemoveItem(StackList[(EntryCount+1)/2]);
    176     Output(out);
    177   //}
    178   //if (StackList[CurrentFirstEntry] != NULL) {
    179     *out << "Removing first element  ..." << endl;
    180     RemoveItem(StackList[CurrentFirstEntry]);
    181     Output(out);
    182   //}
    183   //if (StackList[CurrentLastEntry] != NULL) {
    184     *out << "Removing last element ..." << endl;
    185     RemoveItem(StackList[CurrentLastEntry]);
    186     Output(out);
    187   //}
    188   *out << "Clearing stack ... " << endl; 
    189   ClearStack();
    190   Output(out);
    191   if (IsEmpty())
    192     *out << "Stack is empty as supposed to be!" << endl;
    193   else
    194     *out << "ERROR: Stack is not as empty as supposed to be!" << endl;
    195   *out << "done." << endl;
     160        T Walker = test;
     161        *out << Verbose(1) << "Testing the snake stack..." << endl;
     162        for (int i=0;i<EntryCount;i++) {
     163                *out << Verbose(2) << "Filling " << i << "th element of stack." << endl;
     164                Push(Walker);
     165                Walker=Walker->next;
     166        }
     167        *out << endl;
     168        Output(out);
     169        if (IsFull())
     170                *out << "Stack is full as supposed to be!" << endl;
     171        else
     172                *out << "ERROR: Stack is not as full as supposed to be!" << endl;
     173        //if (StackList[(EntryCount+1)/2] != NULL) {
     174                *out << "Removing element in the middle ..." << endl;
     175                RemoveItem(StackList[(EntryCount+1)/2]);
     176                Output(out);
     177        //}
     178        //if (StackList[CurrentFirstEntry] != NULL) {
     179                *out << "Removing first element ..." << endl;
     180                RemoveItem(StackList[CurrentFirstEntry]);
     181                Output(out);
     182        //}
     183        //if (StackList[CurrentLastEntry] != NULL) {
     184                *out << "Removing last element ..." << endl;
     185                RemoveItem(StackList[CurrentLastEntry]);
     186                Output(out);
     187        //}
     188        *out << "Clearing stack ... " << endl;
     189        ClearStack();
     190        Output(out);
     191        if (IsEmpty())
     192                *out << "Stack is empty as supposed to be!" << endl;
     193        else
     194                *out << "ERROR: Stack is not as empty as supposed to be!" << endl;
     195        *out << "done." << endl;
    196196};
    197197
     
    201201template <typename T> void StackClass<T>::Output(ofstream *out) const
    202202{
    203   *out << "Contents of Stack: ";
    204   for(int i=0;i<EntryCount;i++) {
    205     *out << "\t";
    206     if (i == CurrentFirstEntry)
    207       *out << " 1";
    208     if  (i == CurrentLastEntry)
    209       *out << " "<< EntryCount;
    210     if (i ==  NextFreeField)
    211       *out << " F";
    212     *out << ": " << StackList[i];
    213   }
    214   *out << endl;
     203        *out << "Contents of Stack: ";
     204        for(int i=0;i<EntryCount;i++) {
     205                *out << "\t";
     206                if (i == CurrentFirstEntry)
     207                        *out << " 1";
     208                if      (i == CurrentLastEntry)
     209                        *out << " "<< EntryCount;
     210                if (i ==        NextFreeField)
     211                        *out << " F";
     212                *out << ": " << StackList[i];
     213        }
     214        *out << endl;
    215215};
    216216
     
    222222template <typename T> bool StackClass<T>::IsEmpty()
    223223{
    224   return((NextFreeField == CurrentFirstEntry) && (CurrentLastEntry == CurrentFirstEntry));
     224        return((NextFreeField == CurrentFirstEntry) && (CurrentLastEntry == CurrentFirstEntry));
    225225};
    226226
     
    232232template <typename T> bool StackClass<T>::IsFull()
    233233{
    234   return((NextFreeField == CurrentFirstEntry) && (CurrentLastEntry != CurrentFirstEntry));
     234        return((NextFreeField == CurrentFirstEntry) && (CurrentLastEntry != CurrentFirstEntry));
    235235};
    236236
     
    242242template <typename T> int StackClass<T>::ItemCount()
    243243{
    244   //cout << "Stack: CurrentLastEntry " << CurrentLastEntry<< "\tCurrentFirstEntry " << CurrentFirstEntry << "\tEntryCount " << EntryCount << "." << endl;
    245   return((NextFreeField + (EntryCount - CurrentFirstEntry)) % EntryCount);
     244        //cout << "Stack: CurrentLastEntry " << CurrentLastEntry<< "\tCurrentFirstEntry " << CurrentFirstEntry << "\tEntryCount " << EntryCount << "." << endl;
     245        return((NextFreeField + (EntryCount - CurrentFirstEntry)) % EntryCount);
    246246};
    247247
     
    251251template <typename T> void StackClass<T>::ClearStack()
    252252{
    253   for(int i=EntryCount; i--;)
    254     StackList[i] = NULL;
    255   CurrentFirstEntry = 0;
    256   CurrentLastEntry = 0;
    257   NextFreeField = 0;
     253        for(int i=EntryCount; i--;)
     254                StackList[i] = NULL;
     255        CurrentFirstEntry = 0;
     256        CurrentLastEntry = 0;
     257        NextFreeField = 0;
    258258};
    259259
  • src/valence.db

    • Property mode changed from 100644 to 100755
  • src/vector.cpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    2828double Vector::DistanceSquared(const Vector *y) const
    2929{
    30   double res = 0.;
    31   for (int i=NDIM;i--;)
    32     res += (x[i]-y->x[i])*(x[i]-y->x[i]);
    33   return (res);
     30        double res = 0.;
     31        for (int i=NDIM;i--;)
     32                res += (x[i]-y->x[i])*(x[i]-y->x[i]);
     33        return (res);
    3434};
    3535
     
    4040double Vector::Distance(const Vector *y) const
    4141{
    42   double res = 0.;
    43   for (int i=NDIM;i--;)
    44     res += (x[i]-y->x[i])*(x[i]-y->x[i]);
    45   return (sqrt(res));
     42        double res = 0.;
     43        for (int i=NDIM;i--;)
     44                res += (x[i]-y->x[i])*(x[i]-y->x[i]);
     45        return (sqrt(res));
     46};
     47
     48/** Calculates distance between this and another vector in a periodic cell.
     49 * \param *y array to second vector
     50 * \param *cell_size 6-dimensional array with (xx, xy, yy, xz, yz, zz) entries specifying the periodic cell
     51 * \return \f$| x - y |\f$
     52 */
     53double Vector::PeriodicDistance(const Vector *y, const double *cell_size) const
     54{
     55        double res = Distance(y), tmp, matrix[NDIM*NDIM];
     56        Vector Shiftedy, TranslationVector;
     57        int N[NDIM];
     58        matrix[0] = cell_size[0];
     59        matrix[1] = cell_size[1];
     60        matrix[2] = cell_size[3];
     61        matrix[3] = cell_size[1];
     62        matrix[4] = cell_size[2];
     63        matrix[5] = cell_size[4];
     64        matrix[6] = cell_size[3];
     65        matrix[7] = cell_size[4];
     66        matrix[8] = cell_size[5];
     67        // in order to check the periodic distance, translate one of the vectors into each of the 27 neighbouring cells
     68        for (N[0]=-1;N[0]<=1;N[0]++)
     69                for (N[1]=-1;N[1]<=1;N[1]++)
     70                        for (N[2]=-1;N[2]<=1;N[2]++) {
     71                                // create the translation vector
     72                                TranslationVector.Zero();
     73                                for (int i=NDIM;i--;)
     74                                        TranslationVector.x[i] = (double)N[i];
     75                                TranslationVector.MatrixMultiplication(matrix);
     76                                // add onto the original vector to compare with
     77                                Shiftedy.CopyVector(y);
     78                                Shiftedy.AddVector(&TranslationVector);
     79                                // get distance and compare with minimum so far
     80                                tmp = Distance(&Shiftedy);
     81                                if (tmp < res) res = tmp;
     82                        }
     83        return (res);
    4684};
    4785
     
    5189 * \return \f$| x - y |^2\f$
    5290 */
    53 double Vector::PeriodicDistance(const Vector *y, const double *cell_size) const
    54 {
    55   double res = Distance(y), tmp, matrix[NDIM*NDIM];
    56   Vector Shiftedy, TranslationVector;
    57   int N[NDIM];
    58   matrix[0] = cell_size[0];
    59   matrix[1] = cell_size[1];
    60   matrix[2] = cell_size[3];
    61   matrix[3] = cell_size[1];
    62   matrix[4] = cell_size[2];
    63   matrix[5] = cell_size[4];
    64   matrix[6] = cell_size[3];
    65   matrix[7] = cell_size[4];
    66   matrix[8] = cell_size[5];
    67   // in order to check the periodic distance, translate one of the vectors into each of the 27 neighbouring cells
    68   for (N[0]=-1;N[0]<=1;N[0]++)
    69     for (N[1]=-1;N[1]<=1;N[1]++)
    70       for (N[2]=-1;N[2]<=1;N[2]++) {
    71         // create the translation vector
    72         TranslationVector.Zero();
    73         for (int i=NDIM;i--;)
    74           TranslationVector.x[i] = (double)N[i];
    75         TranslationVector.MatrixMultiplication(matrix);
    76         // add onto the original vector to compare with
    77         Shiftedy.CopyVector(y);
    78         Shiftedy.AddVector(&TranslationVector);
    79         // get distance and compare with minimum so far
    80         tmp = Distance(&Shiftedy);
    81         if (tmp < res) res = tmp;
    82       }
    83   return (res);
     91double Vector::PeriodicDistanceSquared(const Vector *y, const double *cell_size) const
     92{
     93        double res = DistanceSquared(y), tmp, matrix[NDIM*NDIM];
     94        Vector Shiftedy, TranslationVector;
     95        int N[NDIM];
     96        matrix[0] = cell_size[0];
     97        matrix[1] = cell_size[1];
     98        matrix[2] = cell_size[3];
     99        matrix[3] = cell_size[1];
     100        matrix[4] = cell_size[2];
     101        matrix[5] = cell_size[4];
     102        matrix[6] = cell_size[3];
     103        matrix[7] = cell_size[4];
     104        matrix[8] = cell_size[5];
     105        // in order to check the periodic distance, translate one of the vectors into each of the 27 neighbouring cells
     106        for (N[0]=-1;N[0]<=1;N[0]++)
     107                for (N[1]=-1;N[1]<=1;N[1]++)
     108                        for (N[2]=-1;N[2]<=1;N[2]++) {
     109                                // create the translation vector
     110                                TranslationVector.Zero();
     111                                for (int i=NDIM;i--;)
     112                                        TranslationVector.x[i] = (double)N[i];
     113                                TranslationVector.MatrixMultiplication(matrix);
     114                                // add onto the original vector to compare with
     115                                Shiftedy.CopyVector(y);
     116                                Shiftedy.AddVector(&TranslationVector);
     117                                // get distance and compare with minimum so far
     118                                tmp = DistanceSquared(&Shiftedy);
     119                                if (tmp < res) res = tmp;
     120                        }
     121        return (res);
    84122};
    85123
     
    90128void Vector::KeepPeriodic(ofstream *out, double *matrix)
    91129{
    92 //  int N[NDIM];
    93 //  bool flag = false;
    94   //vector Shifted, TranslationVector;
    95   Vector TestVector;
    96 //  *out << Verbose(1) << "Begin of KeepPeriodic." << endl;
    97 //  *out << Verbose(2) << "Vector is: ";
    98 //  Output(out);
    99 //  *out << endl;
    100   TestVector.CopyVector(this);
    101   TestVector.InverseMatrixMultiplication(matrix);
    102   for(int i=NDIM;i--;) { // correct periodically
    103     if (TestVector.x[i] < 0) {  // get every coefficient into the interval [0,1)
    104       TestVector.x[i] += ceil(TestVector.x[i]);
    105     } else {
    106       TestVector.x[i] -= floor(TestVector.x[i]);
    107     }
    108   }
    109   TestVector.MatrixMultiplication(matrix);
    110   CopyVector(&TestVector);
    111 //  *out << Verbose(2) << "New corrected vector is: ";
    112 //  Output(out);
    113 //  *out << endl;
    114 //  *out << Verbose(1) << "End of KeepPeriodic." << endl;
     130//      int N[NDIM];
     131//      bool flag = false;
     132        //vector Shifted, TranslationVector;
     133        Vector TestVector;
     134//      *out << Verbose(1) << "Begin of KeepPeriodic." << endl;
     135//      *out << Verbose(2) << "Vector is: ";
     136//      Output(out);
     137//      *out << endl;
     138        TestVector.CopyVector(this);
     139        TestVector.InverseMatrixMultiplication(matrix);
     140        for(int i=NDIM;i--;) { // correct periodically
     141                if (TestVector.x[i] < 0) {      // get every coefficient into the interval [0,1)
     142                        TestVector.x[i] += ceil(TestVector.x[i]);
     143                } else {
     144                        TestVector.x[i] -= floor(TestVector.x[i]);
     145                }
     146        }
     147        TestVector.MatrixMultiplication(matrix);
     148        CopyVector(&TestVector);
     149//      *out << Verbose(2) << "New corrected vector is: ";
     150//      Output(out);
     151//      *out << endl;
     152//      *out << Verbose(1) << "End of KeepPeriodic." << endl;
    115153};
    116154
     
    121159double Vector::ScalarProduct(const Vector *y) const
    122160{
    123   double res = 0.;
    124   for (int i=NDIM;i--;)
    125     res += x[i]*y->x[i];
    126   return (res);
     161        double res = 0.;
     162        for (int i=NDIM;i--;)
     163                res += x[i]*y->x[i];
     164        return (res);
    127165};
    128166
    129167
    130168/** Calculates VectorProduct between this and another vector.
    131  *  -# returns the Product in place of vector from which it was initiated
    132  *  -# ATTENTION: Only three dim.
    133  *  \param *y array to vector with which to calculate crossproduct
    134  *  \return \f$ x \times y \f&
     169 *      -# returns the Product in place of vector from which it was initiated
     170 *      -# ATTENTION: Only three dim.
     171 *      \param *y array to vector with which to calculate crossproduct
     172 *      \return \f$ x \times y \f&
    135173 */
    136174void Vector::VectorProduct(const Vector *y)
    137175{
    138   Vector tmp;
    139   tmp.x[0] = x[1]* (y->x[2]) - x[2]* (y->x[1]);
    140   tmp.x[1] = x[2]* (y->x[0]) - x[0]* (y->x[2]);
    141   tmp.x[2] = x[0]* (y->x[1]) - x[1]* (y->x[0]);
    142   this->CopyVector(&tmp);
     176        Vector tmp;
     177        tmp.x[0] = x[1]* (y->x[2]) - x[2]* (y->x[1]);
     178        tmp.x[1] = x[2]* (y->x[0]) - x[0]* (y->x[2]);
     179        tmp.x[2] = x[0]* (y->x[1]) - x[1]* (y->x[0]);
     180        this->CopyVector(&tmp);
    143181
    144182};
     
    151189void Vector::ProjectOntoPlane(const Vector *y)
    152190{
    153   Vector tmp;
    154   tmp.CopyVector(y);
    155   tmp.Normalize();
    156   tmp.Scale(ScalarProduct(&tmp));
    157   this->SubtractVector(&tmp);
     191        Vector tmp;
     192        tmp.CopyVector(y);
     193        tmp.Normalize();
     194        tmp.Scale(ScalarProduct(&tmp));
     195        this->SubtractVector(&tmp);
    158196};
    159197
     
    164202double Vector::Projection(const Vector *y) const
    165203{
    166   return (ScalarProduct(y));
     204        return (ScalarProduct(y));
    167205};
    168206
     
    172210double Vector::Norm() const
    173211{
    174   double res = 0.;
    175   for (int i=NDIM;i--;)
    176     res += this->x[i]*this->x[i];
    177   return (sqrt(res));
     212        double res = 0.;
     213        for (int i=NDIM;i--;)
     214                res += this->x[i]*this->x[i];
     215        return (sqrt(res));
    178216};
    179217
     
    182220void Vector::Normalize()
    183221{
    184   double res = 0.;
    185   for (int i=NDIM;i--;)
    186     res += this->x[i]*this->x[i];
    187   if (fabs(res) > MYEPSILON)
    188     res = 1./sqrt(res);
    189   Scale(&res);
     222        double res = 0.;
     223        for (int i=NDIM;i--;)
     224                res += this->x[i]*this->x[i];
     225        if (fabs(res) > MYEPSILON)
     226                res = 1./sqrt(res);
     227        Scale(&res);
    190228};
    191229
     
    194232void Vector::Zero()
    195233{
    196   for (int i=NDIM;i--;)
    197     this->x[i] = 0.;
     234        for (int i=NDIM;i--;)
     235                this->x[i] = 0.;
    198236};
    199237
     
    202240void Vector::One(double one)
    203241{
    204   for (int i=NDIM;i--;)
    205     this->x[i] = one;
     242        for (int i=NDIM;i--;)
     243                this->x[i] = one;
    206244};
    207245
     
    210248void Vector::Init(double x1, double x2, double x3)
    211249{
    212   x[0] = x1;
    213   x[1] = x2;
    214   x[2] = x3;
     250        x[0] = x1;
     251        x[1] = x2;
     252        x[2] = x3;
    215253};
    216254
     
    219257 * \return \f$\acos\bigl(frac{\langle x, y \rangle}{|x||y|}\bigr)\f$
    220258 */
    221 double Vector::Angle(Vector *y) const
    222 {
    223   return acos(this->ScalarProduct(y)/Norm()/y->Norm());
     259double Vector::Angle(const Vector *y) const
     260{
     261        return acos(this->ScalarProduct(y)/Norm()/y->Norm());
    224262};
    225263
     
    230268void Vector::RotateVector(const Vector *axis, const double alpha)
    231269{
    232   Vector a,y;
    233   // normalise this vector with respect to axis
    234   a.CopyVector(this);
    235   a.Scale(Projection(axis));
    236   SubtractVector(&a);
    237   // construct normal vector
    238   y.MakeNormalVector(axis,this);
    239   y.Scale(Norm());
    240   // scale normal vector by sine and this vector by cosine
    241   y.Scale(sin(alpha));
    242   Scale(cos(alpha));
    243   // add scaled normal vector onto this vector
    244   AddVector(&y);
    245   // add part in axis direction
    246   AddVector(&a);
     270        Vector a,y;
     271        // normalise this vector with respect to axis
     272        a.CopyVector(this);
     273        a.Scale(Projection(axis));
     274        SubtractVector(&a);
     275        // construct normal vector
     276        y.MakeNormalVector(axis,this);
     277        y.Scale(Norm());
     278        // scale normal vector by sine and this vector by cosine
     279        y.Scale(sin(alpha));
     280        Scale(cos(alpha));
     281        // add scaled normal vector onto this vector
     282        AddVector(&y);
     283        // add part in axis direction
     284        AddVector(&a);
    247285};
    248286
     
    254292Vector& operator+=(Vector& a, const Vector& b)
    255293{
    256   a.AddVector(&b);
    257   return a;
     294        a.AddVector(&b);
     295        return a;
    258296};
    259297/** factor each component of \a a times a double \a m.
     
    264302Vector& operator*=(Vector& a, const double m)
    265303{
    266   a.Scale(m);
    267   return a;
    268 };
    269 
    270 /** Sums two vectors \a  and \b component-wise.
     304        a.Scale(m);
     305        return a;
     306};
     307
     308/** Sums two vectors \a and \b component-wise.
    271309 * \param a first vector
    272310 * \param b second vector
     
    275313Vector& operator+(const Vector& a, const Vector& b)
    276314{
    277   Vector *x = new Vector;
    278   x->CopyVector(&a);
    279   x->AddVector(&b);
    280   return *x;
     315        Vector *x = new Vector;
     316        x->CopyVector(&a);
     317        x->AddVector(&b);
     318        return *x;
    281319};
    282320
     
    288326Vector& operator*(const Vector& a, const double m)
    289327{
    290   Vector *x = new Vector;
    291   x->CopyVector(&a);
    292   x->Scale(m);
    293   return *x;
     328        Vector *x = new Vector;
     329        x->CopyVector(&a);
     330        x->Scale(m);
     331        return *x;
    294332};
    295333
     
    300338bool Vector::Output(ofstream *out) const
    301339{
    302   if (out != NULL) {
    303     *out << "(";
    304     for (int i=0;i<NDIM;i++) {
    305       *out << x[i];
    306       if (i != 2)
    307         *out << ",";
    308     }
    309     *out << ")";
    310     return true;
    311   } else
    312     return false;
    313 };
    314 
    315 ofstream& operator<<(ofstream& ost,Vector& m)
    316 {
    317         m.Output(&ost);
     340        if (out != NULL) {
     341                *out << "(";
     342                for (int i=0;i<NDIM;i++) {
     343                        *out << x[i];
     344                        if (i != 2)
     345                                *out << ",";
     346                }
     347                *out << ")";
     348                return true;
     349        } else
     350                return false;
     351};
     352
     353ostream& operator<<(ostream& ost,Vector& m)
     354{
     355        ost << "(";
     356        for (int i=0;i<NDIM;i++) {
     357                ost << m.x[i];
     358                if (i != 2)
     359                        ost << ",";
     360        }
     361        ost << ")";
    318362        return ost;
    319363};
     
    324368void Vector::Scale(double **factor)
    325369{
    326   for (int i=NDIM;i--;)
    327     x[i] *= (*factor)[i];
     370        for (int i=NDIM;i--;)
     371                x[i] *= (*factor)[i];
    328372};
    329373
    330374void Vector::Scale(double *factor)
    331375{
    332   for (int i=NDIM;i--;)
    333     x[i] *= *factor;
     376        for (int i=NDIM;i--;)
     377                x[i] *= *factor;
    334378};
    335379
    336380void Vector::Scale(double factor)
    337381{
    338   for (int i=NDIM;i--;)
    339     x[i] *= factor;
     382        for (int i=NDIM;i--;)
     383                x[i] *= factor;
    340384};
    341385
     
    345389void Vector::Translate(const Vector *trans)
    346390{
    347   for (int i=NDIM;i--;)
    348     x[i] += trans->x[i];
     391        for (int i=NDIM;i--;)
     392                x[i] += trans->x[i];
    349393};
    350394
     
    354398void Vector::MatrixMultiplication(double *M)
    355399{
    356   Vector C;
    357   // do the matrix multiplication
    358   C.x[0] = M[0]*x[0]+M[3]*x[1]+M[6]*x[2];
    359   C.x[1] = M[1]*x[0]+M[4]*x[1]+M[7]*x[2];
    360   C.x[2] = M[2]*x[0]+M[5]*x[1]+M[8]*x[2];
    361   // transfer the result into this
    362   for (int i=NDIM;i--;)
    363     x[i] = C.x[i];
     400        Vector C;
     401        // do the matrix multiplication
     402        C.x[0] = M[0]*x[0]+M[3]*x[1]+M[6]*x[2];
     403        C.x[1] = M[1]*x[0]+M[4]*x[1]+M[7]*x[2];
     404        C.x[2] = M[2]*x[0]+M[5]*x[1]+M[8]*x[2];
     405        // transfer the result into this
     406        for (int i=NDIM;i--;)
     407                x[i] = C.x[i];
    364408};
    365409
     
    369413void Vector::InverseMatrixMultiplication(double *A)
    370414{
    371   Vector C;
    372   double B[NDIM*NDIM];
    373   double detA = RDET3(A);
    374   double detAReci;
    375 
    376   // calculate the inverse B
    377   if (fabs(detA) > MYEPSILON) {;  // RDET3(A) yields precisely zero if A irregular
    378     detAReci = 1./detA;
    379     B[0] =  detAReci*RDET2(A[4],A[5],A[7],A[8]);    // A_11
    380     B[1] = -detAReci*RDET2(A[1],A[2],A[7],A[8]);    // A_12
    381     B[2] =  detAReci*RDET2(A[1],A[2],A[4],A[5]);    // A_13
    382     B[3] = -detAReci*RDET2(A[3],A[5],A[6],A[8]);    // A_21
    383     B[4] =  detAReci*RDET2(A[0],A[2],A[6],A[8]);    // A_22
    384     B[5] = -detAReci*RDET2(A[0],A[2],A[3],A[5]);    // A_23
    385     B[6] =  detAReci*RDET2(A[3],A[4],A[6],A[7]);    // A_31
    386     B[7] = -detAReci*RDET2(A[0],A[1],A[6],A[7]);    // A_32
    387     B[8] =  detAReci*RDET2(A[0],A[1],A[3],A[4]);    // A_33
    388 
    389     // do the matrix multiplication
    390     C.x[0] = B[0]*x[0]+B[3]*x[1]+B[6]*x[2];
    391     C.x[1] = B[1]*x[0]+B[4]*x[1]+B[7]*x[2];
    392     C.x[2] = B[2]*x[0]+B[5]*x[1]+B[8]*x[2];
    393     // transfer the result into this
    394     for (int i=NDIM;i--;)
    395       x[i] = C.x[i];
    396   } else {
    397     cerr << "ERROR: inverse of matrix does not exists!" << endl;
    398   }
     415        Vector C;
     416        double B[NDIM*NDIM];
     417        double detA = RDET3(A);
     418        double detAReci;
     419
     420        // calculate the inverse B
     421        if (fabs(detA) > MYEPSILON) {;  // RDET3(A) yields precisely zero if A irregular
     422                detAReci = 1./detA;
     423                B[0] =  detAReci*RDET2(A[4],A[5],A[7],A[8]);            // A_11
     424                B[1] = -detAReci*RDET2(A[1],A[2],A[7],A[8]);            // A_12
     425                B[2] =  detAReci*RDET2(A[1],A[2],A[4],A[5]);            // A_13
     426                B[3] = -detAReci*RDET2(A[3],A[5],A[6],A[8]);            // A_21
     427                B[4] =  detAReci*RDET2(A[0],A[2],A[6],A[8]);            // A_22
     428                B[5] = -detAReci*RDET2(A[0],A[2],A[3],A[5]);            // A_23
     429                B[6] =  detAReci*RDET2(A[3],A[4],A[6],A[7]);            // A_31
     430                B[7] = -detAReci*RDET2(A[0],A[1],A[6],A[7]);            // A_32
     431                B[8] =  detAReci*RDET2(A[0],A[1],A[3],A[4]);            // A_33
     432
     433                // do the matrix multiplication
     434                C.x[0] = B[0]*x[0]+B[3]*x[1]+B[6]*x[2];
     435                C.x[1] = B[1]*x[0]+B[4]*x[1]+B[7]*x[2];
     436                C.x[2] = B[2]*x[0]+B[5]*x[1]+B[8]*x[2];
     437                // transfer the result into this
     438                for (int i=NDIM;i--;)
     439                        x[i] = C.x[i];
     440        } else {
     441                cerr << "ERROR: inverse of matrix does not exists!" << endl;
     442        }
    399443};
    400444
     
    409453void Vector::LinearCombinationOfVectors(const Vector *x1, const Vector *x2, const Vector *x3, double *factors)
    410454{
    411   for(int i=NDIM;i--;)
    412     x[i] = factors[0]*x1->x[i] + factors[1]*x2->x[i] + factors[2]*x3->x[i];
     455        for(int i=NDIM;i--;)
     456                x[i] = factors[0]*x1->x[i] + factors[1]*x2->x[i] + factors[2]*x3->x[i];
    413457};
    414458
     
    418462void Vector::Mirror(const Vector *n)
    419463{
    420   double projection;
    421   projection = ScalarProduct(n)/n->ScalarProduct(n);    // remove constancy from n (keep as logical one)
    422   // withdraw projected vector twice from original one
    423   cout << Verbose(1) << "Vector: ";
    424   Output((ofstream *)&cout);
    425   cout << "\t";
    426   for (int i=NDIM;i--;)
    427     x[i] -= 2.*projection*n->x[i];
    428   cout << "Projected vector: ";
    429   Output((ofstream *)&cout);
    430   cout << endl;
     464        double projection;
     465        projection = ScalarProduct(n)/n->ScalarProduct(n);              // remove constancy from n (keep as logical one)
     466        // withdraw projected vector twice from original one
     467        cout << Verbose(1) << "Vector: ";
     468        Output((ofstream *)&cout);
     469        cout << "\t";
     470        for (int i=NDIM;i--;)
     471                x[i] -= 2.*projection*n->x[i];
     472        cout << "Projected vector: ";
     473        Output((ofstream *)&cout);
     474        cout << endl;
    431475};
    432476
     
    440484bool Vector::MakeNormalVector(const Vector *y1, const Vector *y2, const Vector *y3)
    441485{
    442   Vector x1, x2;
    443 
    444   x1.CopyVector(y1);
    445   x1.SubtractVector(y2);
    446   x2.CopyVector(y3);
    447   x2.SubtractVector(y2);
    448   if ((x1.Norm()==0) || (x2.Norm()==0)) {
    449     cout << Verbose(4) << "Given vectors are linear dependent." << endl;
    450     return false;
    451   }
    452 //  cout << Verbose(4) << "relative, first plane coordinates:";
    453 //  x1.Output((ofstream *)&cout);
    454 //  cout << endl;
    455 //  cout << Verbose(4) << "second plane coordinates:";
    456 //  x2.Output((ofstream *)&cout);
    457 //  cout << endl;
    458 
    459   this->x[0] = (x1.x[1]*x2.x[2] - x1.x[2]*x2.x[1]);
    460   this->x[1] = (x1.x[2]*x2.x[0] - x1.x[0]*x2.x[2]);
    461   this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]);
    462   Normalize();
    463 
    464   return true;
     486        Vector x1, x2;
     487
     488        x1.CopyVector(y1);
     489        x1.SubtractVector(y2);
     490        x2.CopyVector(y3);
     491        x2.SubtractVector(y2);
     492        if ((fabs(x1.Norm()) < MYEPSILON) || (fabs(x2.Norm()) < MYEPSILON) || (fabs(x1.Angle(&x2)) < MYEPSILON)) {
     493                cout << Verbose(4) << "Given vectors are linear dependent." << endl;
     494                return false;
     495        }
     496//      cout << Verbose(4) << "relative, first plane coordinates:";
     497//      x1.Output((ofstream *)&cout);
     498//      cout << endl;
     499//      cout << Verbose(4) << "second plane coordinates:";
     500//      x2.Output((ofstream *)&cout);
     501//      cout << endl;
     502
     503        this->x[0] = (x1.x[1]*x2.x[2] - x1.x[2]*x2.x[1]);
     504        this->x[1] = (x1.x[2]*x2.x[0] - x1.x[0]*x2.x[2]);
     505        this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]);
     506        Normalize();
     507
     508        return true;
    465509};
    466510
     
    476520bool Vector::MakeNormalVector(const Vector *y1, const Vector *y2)
    477521{
    478   Vector x1,x2;
    479   x1.CopyVector(y1);
    480   x2.CopyVector(y2);
    481   Zero();
    482   if ((x1.Norm()==0) || (x2.Norm()==0)) {
    483     cout << Verbose(4) << "Given vectors are linear dependent." << endl;
    484     return false;
    485   }
    486 //  cout << Verbose(4) << "relative, first plane coordinates:";
    487 //  x1.Output((ofstream *)&cout);
    488 //  cout << endl;
    489 //  cout << Verbose(4) << "second plane coordinates:";
    490 //  x2.Output((ofstream *)&cout);
    491 //  cout << endl;
    492 
    493   this->x[0] = (x1.x[1]*x2.x[2] - x1.x[2]*x2.x[1]);
    494   this->x[1] = (x1.x[2]*x2.x[0] - x1.x[0]*x2.x[2]);
    495   this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]);
    496   Normalize();
    497 
    498   return true;
     522        Vector x1,x2;
     523        x1.CopyVector(y1);
     524        x2.CopyVector(y2);
     525        Zero();
     526        if ((fabs(x1.Norm()) < MYEPSILON) || (fabs(x2.Norm()) < MYEPSILON) || (fabs(x1.Angle(&x2)) < MYEPSILON)) {
     527                cout << Verbose(4) << "Given vectors are linear dependent." << endl;
     528                return false;
     529        }
     530//      cout << Verbose(4) << "relative, first plane coordinates:";
     531//      x1.Output((ofstream *)&cout);
     532//      cout << endl;
     533//      cout << Verbose(4) << "second plane coordinates:";
     534//      x2.Output((ofstream *)&cout);
     535//      cout << endl;
     536
     537        this->x[0] = (x1.x[1]*x2.x[2] - x1.x[2]*x2.x[1]);
     538        this->x[1] = (x1.x[2]*x2.x[0] - x1.x[0]*x2.x[2]);
     539        this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]);
     540        Normalize();
     541
     542        return true;
    499543};
    500544
     
    507551{
    508552        bool result = false;
    509   Vector x1;
    510   x1.CopyVector(y1);
    511   x1.Scale(x1.Projection(this));
    512   SubtractVector(&x1);
    513   for (int i=NDIM;i--;)
    514           result = result || (fabs(x[i]) > MYEPSILON);
    515 
    516   return result;
     553        Vector x1;
     554        x1.CopyVector(y1);
     555        x1.Scale(x1.Projection(this));
     556        SubtractVector(&x1);
     557        for (int i=NDIM;i--;)
     558                result = result || (fabs(x[i]) > MYEPSILON);
     559
     560        return result;
    517561};
    518562
     
    525569bool Vector::GetOneNormalVector(const Vector *GivenVector)
    526570{
    527   int Components[NDIM]; // contains indices of non-zero components
    528   int Last = 0;  // count the number of non-zero entries in vector
    529   int j;  // loop variables
    530   double norm;
    531 
    532   cout << Verbose(4);
    533   GivenVector->Output((ofstream *)&cout);
    534   cout << endl;
    535   for (j=NDIM;j--;)
    536     Components[j] = -1;
    537   // find two components != 0
    538   for (j=0;j<NDIM;j++)
    539     if (fabs(GivenVector->x[j]) > MYEPSILON)
    540       Components[Last++] = j;
    541   cout << Verbose(4) << Last << " Components != 0: (" << Components[0] << "," << Components[1] << "," << Components[2] << ")" << endl;
    542 
    543   switch(Last) {
    544     case 3:  // threecomponent system
    545     case 2:  // two component system
    546       norm = sqrt(1./(GivenVector->x[Components[1]]*GivenVector->x[Components[1]]) + 1./(GivenVector->x[Components[0]]*GivenVector->x[Components[0]]));
    547       x[Components[2]] = 0.;
    548       // in skp both remaining parts shall become zero but with opposite sign and third is zero
    549       x[Components[1]] = -1./GivenVector->x[Components[1]] / norm;
    550       x[Components[0]] = 1./GivenVector->x[Components[0]] / norm;
    551       return true;
    552       break;
    553     case 1: // one component system
    554       // set sole non-zero component to 0, and one of the other zero component pendants to 1
    555       x[(Components[0]+2)%NDIM] = 0.;
    556       x[(Components[0]+1)%NDIM] = 1.;
    557       x[Components[0]] = 0.;
    558       return true;
    559       break;
    560     default:
    561       return false;
    562   }
     571        int Components[NDIM]; // contains indices of non-zero components
     572        int Last = 0;    // count the number of non-zero entries in vector
     573        int j;  // loop variables
     574        double norm;
     575
     576        cout << Verbose(4);
     577        GivenVector->Output((ofstream *)&cout);
     578        cout << endl;
     579        for (j=NDIM;j--;)
     580                Components[j] = -1;
     581        // find two components != 0
     582        for (j=0;j<NDIM;j++)
     583                if (fabs(GivenVector->x[j]) > MYEPSILON)
     584                        Components[Last++] = j;
     585        cout << Verbose(4) << Last << " Components != 0: (" << Components[0] << "," << Components[1] << "," << Components[2] << ")" << endl;
     586
     587        switch(Last) {
     588                case 3: // threecomponent system
     589                case 2: // two component system
     590                        norm = sqrt(1./(GivenVector->x[Components[1]]*GivenVector->x[Components[1]]) + 1./(GivenVector->x[Components[0]]*GivenVector->x[Components[0]]));
     591                        x[Components[2]] = 0.;
     592                        // in skp both remaining parts shall become zero but with opposite sign and third is zero
     593                        x[Components[1]] = -1./GivenVector->x[Components[1]] / norm;
     594                        x[Components[0]] = 1./GivenVector->x[Components[0]] / norm;
     595                        return true;
     596                        break;
     597                case 1: // one component system
     598                        // set sole non-zero component to 0, and one of the other zero component pendants to 1
     599                        x[(Components[0]+2)%NDIM] = 0.;
     600                        x[(Components[0]+1)%NDIM] = 1.;
     601                        x[Components[0]] = 0.;
     602                        return true;
     603                        break;
     604                default:
     605                        return false;
     606        }
    563607};
    564608
     
    571615double Vector::CutsPlaneAt(Vector *A, Vector *B, Vector *C)
    572616{
    573 //  cout << Verbose(3) << "For comparison: ";
    574 //  cout << "A " << A->Projection(this) << "\t";
    575 //  cout << "B " << B->Projection(this) << "\t";
    576 //  cout << "C " << C->Projection(this) << "\t";
    577 //  cout << endl;
    578   return A->Projection(this);
     617//      cout << Verbose(3) << "For comparison: ";
     618//      cout << "A " << A->Projection(this) << "\t";
     619//      cout << "B " << B->Projection(this) << "\t";
     620//      cout << "C " << C->Projection(this) << "\t";
     621//      cout << endl;
     622        return A->Projection(this);
    579623};
    580624
     
    594638        }
    595639
    596   int np = 3;
     640        int np = 3;
    597641        struct LSQ_params par;
    598642
    599   const gsl_multimin_fminimizer_type *T =
    600     gsl_multimin_fminimizer_nmsimplex;
    601   gsl_multimin_fminimizer *s = NULL;
    602   gsl_vector *ss, *y;
    603   gsl_multimin_function minex_func;
    604 
    605   size_t iter = 0, i;
    606   int status;
    607   double size;
    608 
    609   /* Initial vertex size vector */
    610   ss = gsl_vector_alloc (np);
    611   y = gsl_vector_alloc (np);
    612 
    613   /* Set all step sizes to 1 */
    614   gsl_vector_set_all (ss, 1.0);
    615 
    616   /* Starting point */
    617   par.vectors = vectors;
     643        const gsl_multimin_fminimizer_type *T =
     644                gsl_multimin_fminimizer_nmsimplex;
     645        gsl_multimin_fminimizer *s = NULL;
     646        gsl_vector *ss, *y;
     647        gsl_multimin_function minex_func;
     648
     649        size_t iter = 0, i;
     650        int status;
     651        double size;
     652
     653        /* Initial vertex size vector */
     654        ss = gsl_vector_alloc (np);
     655        y = gsl_vector_alloc (np);
     656
     657        /* Set all step sizes to 1 */
     658        gsl_vector_set_all (ss, 1.0);
     659
     660        /* Starting point */
     661        par.vectors = vectors;
    618662         par.num = num;
    619663
     
    621665                gsl_vector_set(y, i, (vectors[0]->x[i] - vectors[1]->x[i])/2.);
    622666
    623   /* Initialize method and iterate */
    624   minex_func.f = &LSQ;
    625   minex_func.n = np;
    626   minex_func.params = (void *)&par;
    627 
    628   s = gsl_multimin_fminimizer_alloc (T, np);
    629   gsl_multimin_fminimizer_set (s, &minex_func, y, ss);
    630 
    631   do
    632     {
    633       iter++;
    634       status = gsl_multimin_fminimizer_iterate(s);
    635 
    636       if (status)
    637         break;
    638 
    639       size = gsl_multimin_fminimizer_size (s);
    640       status = gsl_multimin_test_size (size, 1e-2);
    641 
    642       if (status == GSL_SUCCESS)
    643         {
    644           printf ("converged to minimum at\n");
    645         }
    646 
    647       printf ("%5d ", (int)iter);
    648       for (i = 0; i < (size_t)np; i++)
    649         {
    650           printf ("%10.3e ", gsl_vector_get (s->x, i));
    651         }
    652       printf ("f() = %7.3f size = %.3f\n", s->fval, size);
    653     }
    654   while (status == GSL_CONTINUE && iter < 100);
    655 
    656   for (i=(size_t)np;i--;)
    657     this->x[i] = gsl_vector_get(s->x, i);
    658   gsl_vector_free(y);
    659   gsl_vector_free(ss);
    660   gsl_multimin_fminimizer_free (s);
     667        /* Initialize method and iterate */
     668        minex_func.f = &LSQ;
     669        minex_func.n = np;
     670        minex_func.params = (void *)&par;
     671
     672        s = gsl_multimin_fminimizer_alloc (T, np);
     673        gsl_multimin_fminimizer_set (s, &minex_func, y, ss);
     674
     675        do
     676                {
     677                        iter++;
     678                        status = gsl_multimin_fminimizer_iterate(s);
     679
     680                        if (status)
     681                                break;
     682
     683                        size = gsl_multimin_fminimizer_size (s);
     684                        status = gsl_multimin_test_size (size, 1e-2);
     685
     686                        if (status == GSL_SUCCESS)
     687                                {
     688                                        printf ("converged to minimum at\n");
     689                                }
     690
     691                        printf ("%5d ", (int)iter);
     692                        for (i = 0; i < (size_t)np; i++)
     693                                {
     694                                        printf ("%10.3e ", gsl_vector_get (s->x, i));
     695                                }
     696                        printf ("f() = %7.3f size = %.3f\n", s->fval, size);
     697                }
     698        while (status == GSL_CONTINUE && iter < 100);
     699
     700        for (i=(size_t)np;i--;)
     701                this->x[i] = gsl_vector_get(s->x, i);
     702        gsl_vector_free(y);
     703        gsl_vector_free(ss);
     704        gsl_multimin_fminimizer_free (s);
    661705
    662706        return true;
     
    668712void Vector::AddVector(const Vector *y)
    669713{
    670   for (int i=NDIM;i--;)
    671     this->x[i] += y->x[i];
     714        for (int i=NDIM;i--;)
     715                this->x[i] += y->x[i];
    672716}
    673717
     
    677721void Vector::SubtractVector(const Vector *y)
    678722{
    679   for (int i=NDIM;i--;)
    680     this->x[i] -= y->x[i];
     723        for (int i=NDIM;i--;)
     724                this->x[i] -= y->x[i];
    681725}
    682726
     
    686730void Vector::CopyVector(const Vector *y)
    687731{
    688   for (int i=NDIM;i--;)
    689     this->x[i] = y->x[i];
     732        for (int i=NDIM;i--;)
     733                this->x[i] = y->x[i];
    690734}
    691735
     
    697741void Vector::AskPosition(double *cell_size, bool check)
    698742{
    699   char coords[3] = {'x','y','z'};
    700   int j = -1;
    701   for (int i=0;i<3;i++) {
    702     j += i+1;
    703     do {
    704       cout << Verbose(0) << coords[i] << "[0.." << cell_size[j] << "]: ";
    705       cin >> x[i];
    706     } while (((x[i] < 0) || (x[i] >= cell_size[j])) && (check));
    707   }
     743        char coords[3] = {'x','y','z'};
     744        int j = -1;
     745        for (int i=0;i<3;i++) {
     746                j += i+1;
     747                do {
     748                        cout << Verbose(0) << coords[i] << "[0.." << cell_size[j] << "]: ";
     749                        cin >> x[i];
     750                } while (((x[i] < 0) || (x[i] >= cell_size[j])) && (check));
     751        }
    708752};
    709753
     
    725769bool Vector::SolveSystem(Vector *x1, Vector *x2, Vector *y, double alpha, double beta, double c)
    726770{
    727   double D1,D2,D3,E1,E2,F1,F2,F3,p,q=0., A, B1, B2, C;
    728   double ang; // angle on testing
    729   double sign[3];
    730   int i,j,k;
    731   A = cos(alpha) * x1->Norm() * c;
    732   B1 = cos(beta + M_PI/2.) * y->Norm() * c;
    733   B2 = cos(beta) * x2->Norm() * c;
    734   C = c * c;
    735   cout << Verbose(2) << "A " << A << "\tB " << B1 << "\tC " << C << endl;
    736   int flag = 0;
    737   if (fabs(x1->x[0]) < MYEPSILON) { // check for zero components for the later flipping and back-flipping
    738     if (fabs(x1->x[1]) > MYEPSILON) {
    739       flag = 1;
    740     } else if (fabs(x1->x[2]) > MYEPSILON) {
    741       flag = 2;
    742     } else {
    743       return false;
    744     }
    745   }
    746   switch (flag) {
    747     default:
    748     case 0:
    749       break;
    750     case 2:
    751       flip(&x1->x[0],&x1->x[1]);
    752       flip(&x2->x[0],&x2->x[1]);
    753       flip(&y->x[0],&y->x[1]);
    754       //flip(&x[0],&x[1]);
    755       flip(&x1->x[1],&x1->x[2]);
    756       flip(&x2->x[1],&x2->x[2]);
    757       flip(&y->x[1],&y->x[2]);
    758       //flip(&x[1],&x[2]);
    759     case 1:
    760       flip(&x1->x[0],&x1->x[1]);
    761       flip(&x2->x[0],&x2->x[1]);
    762       flip(&y->x[0],&y->x[1]);
    763       //flip(&x[0],&x[1]);
    764       flip(&x1->x[1],&x1->x[2]);
    765       flip(&x2->x[1],&x2->x[2]);
    766       flip(&y->x[1],&y->x[2]);
    767       //flip(&x[1],&x[2]);
    768       break;
    769   }
    770   // now comes the case system
    771   D1 = -y->x[0]/x1->x[0]*x1->x[1]+y->x[1];
    772   D2 = -y->x[0]/x1->x[0]*x1->x[2]+y->x[2];
    773   D3 = y->x[0]/x1->x[0]*A-B1;
    774   cout << Verbose(2) << "D1 " << D1 << "\tD2 " << D2 << "\tD3 " << D3 << "\n";
    775   if (fabs(D1) < MYEPSILON) {
    776     cout << Verbose(2) << "D1 == 0!\n";
    777     if (fabs(D2) > MYEPSILON) {
    778       cout << Verbose(3) << "D2 != 0!\n";
    779       x[2] = -D3/D2;
    780       E1 = A/x1->x[0] + x1->x[2]/x1->x[0]*D3/D2;
    781       E2 = -x1->x[1]/x1->x[0];
    782       cout << Verbose(3) << "E1 " << E1 << "\tE2 " << E2 << "\n";
    783       F1 = E1*E1 + 1.;
    784       F2 = -E1*E2;
    785       F3 = E1*E1 + D3*D3/(D2*D2) - C;
    786       cout << Verbose(3) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n";
    787       if (fabs(F1) < MYEPSILON) {
    788         cout << Verbose(4) << "F1 == 0!\n";
    789         cout << Verbose(4) << "Gleichungssystem linear\n";
    790         x[1] = F3/(2.*F2);
    791       } else {
    792         p = F2/F1;
    793         q = p*p - F3/F1;
    794         cout << Verbose(4) << "p " << p << "\tq " << q << endl;
    795         if (q < 0) {
    796           cout << Verbose(4) << "q < 0" << endl;
    797           return false;
    798         }
    799         x[1] = p + sqrt(q);
    800       }
    801       x[0] =  A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2];
    802     } else {
    803       cout << Verbose(2) << "Gleichungssystem unterbestimmt\n";
    804       return false;
    805     }
    806   } else {
    807     E1 = A/x1->x[0]+x1->x[1]/x1->x[0]*D3/D1;
    808     E2 = x1->x[1]/x1->x[0]*D2/D1 - x1->x[2];
    809     cout << Verbose(2) << "E1 " << E1 << "\tE2 " << E2 << "\n";
    810     F1 = E2*E2 + D2*D2/(D1*D1) + 1.;
    811     F2 = -(E1*E2 + D2*D3/(D1*D1));
    812     F3 = E1*E1 + D3*D3/(D1*D1) - C;
    813     cout << Verbose(2) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n";
    814     if (fabs(F1) < MYEPSILON) {
    815       cout << Verbose(3) << "F1 == 0!\n";
    816       cout << Verbose(3) << "Gleichungssystem linear\n";
    817       x[2] = F3/(2.*F2);
    818     } else {
    819       p = F2/F1;
    820       q = p*p - F3/F1;
    821       cout << Verbose(3) << "p " << p << "\tq " << q << endl;
    822       if (q < 0) {
    823         cout << Verbose(3) << "q < 0" << endl;
    824         return false;
    825       }
    826       x[2] = p + sqrt(q);
    827     }
    828     x[1] = (-D2 * x[2] - D3)/D1;
    829     x[0] = A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2];
    830   }
    831   switch (flag) { // back-flipping
    832     default:
    833     case 0:
    834       break;
    835     case 2:
    836       flip(&x1->x[0],&x1->x[1]);
    837       flip(&x2->x[0],&x2->x[1]);
    838       flip(&y->x[0],&y->x[1]);
    839       flip(&x[0],&x[1]);
    840       flip(&x1->x[1],&x1->x[2]);
    841       flip(&x2->x[1],&x2->x[2]);
    842       flip(&y->x[1],&y->x[2]);
    843       flip(&x[1],&x[2]);
    844     case 1:
    845       flip(&x1->x[0],&x1->x[1]);
    846       flip(&x2->x[0],&x2->x[1]);
    847       flip(&y->x[0],&y->x[1]);
    848       //flip(&x[0],&x[1]);
    849       flip(&x1->x[1],&x1->x[2]);
    850       flip(&x2->x[1],&x2->x[2]);
    851       flip(&y->x[1],&y->x[2]);
    852       flip(&x[1],&x[2]);
    853       break;
    854   }
    855   // one z component is only determined by its radius (without sign)
    856   // thus check eight possible sign flips and determine by checking angle with second vector
    857   for (i=0;i<8;i++) {
    858     // set sign vector accordingly
    859     for (j=2;j>=0;j--) {
    860       k = (i & pot(2,j)) << j;
    861       cout << Verbose(2) << "k " << k << "\tpot(2,j) " << pot(2,j) << endl;
    862       sign[j] = (k == 0) ? 1. : -1.;
    863     }
    864     cout << Verbose(2) << i << ": sign matrix is " << sign[0] << "\t" << sign[1] << "\t" << sign[2] << "\n";
    865     // apply sign matrix
    866     for (j=NDIM;j--;)
    867       x[j] *= sign[j];
    868     // calculate angle and check
    869     ang = x2->Angle (this);
    870     cout << Verbose(1) << i << "th angle " << ang << "\tbeta " << cos(beta) << " :\t";
    871     if (fabs(ang - cos(beta)) < MYEPSILON) {
    872       break;
    873     }
    874     // unapply sign matrix (is its own inverse)
    875     for (j=NDIM;j--;)
    876       x[j] *= sign[j];
    877   }
    878   return true;
    879 };
     771        double D1,D2,D3,E1,E2,F1,F2,F3,p,q=0., A, B1, B2, C;
     772        double ang; // angle on testing
     773        double sign[3];
     774        int i,j,k;
     775        A = cos(alpha) * x1->Norm() * c;
     776        B1 = cos(beta + M_PI/2.) * y->Norm() * c;
     777        B2 = cos(beta) * x2->Norm() * c;
     778        C = c * c;
     779        cout << Verbose(2) << "A " << A << "\tB " << B1 << "\tC " << C << endl;
     780        int flag = 0;
     781        if (fabs(x1->x[0]) < MYEPSILON) { // check for zero components for the later flipping and back-flipping
     782                if (fabs(x1->x[1]) > MYEPSILON) {
     783                        flag = 1;
     784                } else if (fabs(x1->x[2]) > MYEPSILON) {
     785                        flag = 2;
     786                } else {
     787                        return false;
     788                }
     789        }
     790        switch (flag) {
     791                default:
     792                case 0:
     793                        break;
     794                case 2:
     795                        flip(&x1->x[0],&x1->x[1]);
     796                        flip(&x2->x[0],&x2->x[1]);
     797                        flip(&y->x[0],&y->x[1]);
     798                        //flip(&x[0],&x[1]);
     799                        flip(&x1->x[1],&x1->x[2]);
     800                        flip(&x2->x[1],&x2->x[2]);
     801                        flip(&y->x[1],&y->x[2]);
     802                        //flip(&x[1],&x[2]);
     803                case 1:
     804                        flip(&x1->x[0],&x1->x[1]);
     805                        flip(&x2->x[0],&x2->x[1]);
     806                        flip(&y->x[0],&y->x[1]);
     807                        //flip(&x[0],&x[1]);
     808                        flip(&x1->x[1],&x1->x[2]);
     809                        flip(&x2->x[1],&x2->x[2]);
     810                        flip(&y->x[1],&y->x[2]);
     811                        //flip(&x[1],&x[2]);
     812                        break;
     813        }
     814        // now comes the case system
     815        D1 = -y->x[0]/x1->x[0]*x1->x[1]+y->x[1];
     816        D2 = -y->x[0]/x1->x[0]*x1->x[2]+y->x[2];
     817        D3 = y->x[0]/x1->x[0]*A-B1;
     818        cout << Verbose(2) << "D1 " << D1 << "\tD2 " << D2 << "\tD3 " << D3 << "\n";
     819        if (fabs(D1) < MYEPSILON) {
     820                cout << Verbose(2) << "D1 == 0!\n";
     821                if (fabs(D2) > MYEPSILON) {
     822                        cout << Verbose(3) << "D2 != 0!\n";
     823                        x[2] = -D3/D2;
     824                        E1 = A/x1->x[0] + x1->x[2]/x1->x[0]*D3/D2;
     825                        E2 = -x1->x[1]/x1->x[0];
     826                        cout << Verbose(3) << "E1 " << E1 << "\tE2 " << E2 << "\n";
     827                        F1 = E1*E1 + 1.;
     828                        F2 = -E1*E2;
     829                        F3 = E1*E1 + D3*D3/(D2*D2) - C;
     830                        cout << Verbose(3) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n";
     831                        if (fabs(F1) < MYEPSILON) {
     832                                cout << Verbose(4) << "F1 == 0!\n";
     833                                cout << Verbose(4) << "Gleichungssystem linear\n";
     834                                x[1] = F3/(2.*F2);
     835                        } else {
     836                                p = F2/F1;
     837                                q = p*p - F3/F1;
     838                                cout << Verbose(4) << "p " << p << "\tq " << q << endl;
     839                                if (q < 0) {
     840                                        cout << Verbose(4) << "q < 0" << endl;
     841                                        return false;
     842                                }
     843                                x[1] = p + sqrt(q);
     844                        }
     845                        x[0] =  A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2];
     846                } else {
     847                        cout << Verbose(2) << "Gleichungssystem unterbestimmt\n";
     848                        return false;
     849                }
     850        } else {
     851                E1 = A/x1->x[0]+x1->x[1]/x1->x[0]*D3/D1;
     852                E2 = x1->x[1]/x1->x[0]*D2/D1 - x1->x[2];
     853                cout << Verbose(2) << "E1 " << E1 << "\tE2 " << E2 << "\n";
     854                F1 = E2*E2 + D2*D2/(D1*D1) + 1.;
     855                F2 = -(E1*E2 + D2*D3/(D1*D1));
     856                F3 = E1*E1 + D3*D3/(D1*D1) - C;
     857                cout << Verbose(2) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n";
     858                if (fabs(F1) < MYEPSILON) {
     859                        cout << Verbose(3) << "F1 == 0!\n";
     860                        cout << Verbose(3) << "Gleichungssystem linear\n";
     861                        x[2] = F3/(2.*F2);
     862                } else {
     863                        p = F2/F1;
     864                        q = p*p - F3/F1;
     865                        cout << Verbose(3) << "p " << p << "\tq " << q << endl;
     866                        if (q < 0) {
     867                                cout << Verbose(3) << "q < 0" << endl;
     868                                return false;
     869                        }
     870                        x[2] = p + sqrt(q);
     871                }
     872                x[1] = (-D2 * x[2] - D3)/D1;
     873                x[0] = A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2];
     874        }
     875        switch (flag) { // back-flipping
     876                default:
     877                case 0:
     878                        break;
     879                case 2:
     880                        flip(&x1->x[0],&x1->x[1]);
     881                        flip(&x2->x[0],&x2->x[1]);
     882                        flip(&y->x[0],&y->x[1]);
     883                        flip(&x[0],&x[1]);
     884                        flip(&x1->x[1],&x1->x[2]);
     885                        flip(&x2->x[1],&x2->x[2]);
     886                        flip(&y->x[1],&y->x[2]);
     887                        flip(&x[1],&x[2]);
     888                case 1:
     889                        flip(&x1->x[0],&x1->x[1]);
     890                        flip(&x2->x[0],&x2->x[1]);
     891                        flip(&y->x[0],&y->x[1]);
     892                        //flip(&x[0],&x[1]);
     893                        flip(&x1->x[1],&x1->x[2]);
     894                        flip(&x2->x[1],&x2->x[2]);
     895                        flip(&y->x[1],&y->x[2]);
     896                        flip(&x[1],&x[2]);
     897                        break;
     898        }
     899        // one z component is only determined by its radius (without sign)
     900        // thus check eight possible sign flips and determine by checking angle with second vector
     901        for (i=0;i<8;i++) {
     902                // set sign vector accordingly
     903                for (j=2;j>=0;j--) {
     904                        k = (i & pot(2,j)) << j;
     905                        cout << Verbose(2) << "k " << k << "\tpot(2,j) " << pot(2,j) << endl;
     906                        sign[j] = (k == 0) ? 1. : -1.;
     907                }
     908                cout << Verbose(2) << i << ": sign matrix is " << sign[0] << "\t" << sign[1] << "\t" << sign[2] << "\n";
     909                // apply sign matrix
     910                for (j=NDIM;j--;)
     911                        x[j] *= sign[j];
     912                // calculate angle and check
     913                ang = x2->Angle (this);
     914                cout << Verbose(1) << i << "th angle " << ang << "\tbeta " << cos(beta) << " :\t";
     915                if (fabs(ang - cos(beta)) < MYEPSILON) {
     916                        break;
     917                }
     918                // unapply sign matrix (is its own inverse)
     919                for (j=NDIM;j--;)
     920                        x[j] *= sign[j];
     921        }
     922        return true;
     923};
  • src/vector.hpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    88 */
    99class Vector {
    10   public:
    11     double x[NDIM];
     10        public:
     11                double x[NDIM];
    1212
    13   Vector();
    14   Vector(double x1, double x2, double x3);
    15   ~Vector();
     13        Vector();
     14        Vector(double x1, double x2, double x3);
     15        ~Vector();
    1616
    17   double Distance(const Vector *y) const;
    18   double DistanceSquared(const Vector *y) const;
    19   double PeriodicDistance(const Vector *y, const double *cell_size) const;
    20   double ScalarProduct(const Vector *y) const;
    21   double Projection(const Vector *y) const;
    22   double Norm() const ;
    23   double Angle(Vector *y) const;
     17        double Distance(const Vector *y) const;
     18        double DistanceSquared(const Vector *y) const;
     19        double PeriodicDistance(const Vector *y, const double *cell_size) const;
     20        double PeriodicDistanceSquared(const Vector *y, const double *cell_size) const;
     21        double ScalarProduct(const Vector *y) const;
     22        double Projection(const Vector *y) const;
     23        double Norm() const ;
     24        double Angle(const Vector *y) const;
    2425
    25   void AddVector(const Vector *y);
    26   void SubtractVector(const Vector *y);
    27   void CopyVector(const Vector *y);
    28   void RotateVector(const Vector *y, const double alpha);
    29   void VectorProduct(const Vector *y);
    30   void ProjectOntoPlane(const Vector *y);
    31   void Zero();
    32   void One(double one);
    33   void Init(double x1, double x2, double x3);
    34   void Normalize();
    35   void Translate(const Vector *x);
    36   void Mirror(const Vector *x);
    37   void Scale(double **factor);
    38   void Scale(double *factor);
    39   void Scale(double factor);
    40   void MatrixMultiplication(double *M);
    41   void InverseMatrixMultiplication(double *M);
    42   void KeepPeriodic(ofstream *out, double *matrix);
    43   void LinearCombinationOfVectors(const Vector *x1, const Vector *x2, const Vector *x3, double *factors);
    44 
    45   double CutsPlaneAt(Vector *A, Vector *B, Vector *C);
    46   bool GetOneNormalVector(const Vector *x1);
    47   bool MakeNormalVector(const Vector *y1);
    48   bool MakeNormalVector(const Vector *y1, const Vector *y2);
    49   bool MakeNormalVector(const Vector *x1, const Vector *x2, const Vector *x3);
    50   bool SolveSystem(Vector *x1, Vector *x2, Vector *y, double alpha, double beta, double c);
    51   bool LSQdistance(Vector **vectors, int dim);
    52 
    53   void AskPosition(double *cell_size, bool check);
    54   bool Output(ofstream *out) const;
     26        void AddVector(const Vector *y);
     27        void SubtractVector(const Vector *y);
     28        void CopyVector(const Vector *y);
     29        void RotateVector(const Vector *y, const double alpha);
     30        void VectorProduct(const Vector *y);
     31        void ProjectOntoPlane(const Vector *y);
     32        void Zero();
     33        void One(double one);
     34        void Init(double x1, double x2, double x3);
     35        void Normalize();
     36        void Translate(const Vector *x);
     37        void Mirror(const Vector *x);
     38        void Scale(double **factor);
     39        void Scale(double *factor);
     40        void Scale(double factor);
     41        void MatrixMultiplication(double *M);
     42        void InverseMatrixMultiplication(double *M);
     43        void KeepPeriodic(ofstream *out, double *matrix);
     44        void LinearCombinationOfVectors(const Vector *x1, const Vector *x2, const Vector *x3, double *factors);
     45        double CutsPlaneAt(Vector *A, Vector *B, Vector *C);
     46        bool GetOneNormalVector(const Vector *x1);
     47        bool MakeNormalVector(const Vector *y1);
     48        bool MakeNormalVector(const Vector *y1, const Vector *y2);
     49        bool MakeNormalVector(const Vector *x1, const Vector *x2, const Vector *x3);
     50        bool SolveSystem(Vector *x1, Vector *x2, Vector *y, double alpha, double beta, double c);
     51        bool LSQdistance(Vector **vectors, int dim);
     52        void AskPosition(double *cell_size, bool check);
     53        bool Output(ofstream *out) const;
    5554};
    5655
    57 ofstream& operator<<(ofstream& ost, Vector& m);
    58 Vector& operator+=(Vector& a, const Vector& b);
    59 Vector& operator*=(Vector& a, const double m);
    60 Vector& operator*(const Vector& a, const double m);
    61 Vector& operator+(const Vector& a, const Vector& b);
     56ostream & operator << (ostream& ost, Vector &m);
     57//Vector& operator+=(Vector& a, const Vector& b);
     58//Vector& operator*=(Vector& a, const double m);
     59//Vector& operator*(const Vector& a, const double m);
     60//Vector& operator+(const Vector& a, const Vector& b);
    6261
    6362#endif /*VECTOR_HPP_*/
  • src/verbose.cpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    77ostream& Verbose::print (ostream &ost) const
    88{
    9   for (int i=Verbosity;i--;)
    10     ost.put('\t');
    11   //cout << "Verbose(.) called." << endl;
    12   return ost;
     9        for (int i=Verbosity;i--;)
     10                ost.put('\t');
     11        //cout << "Verbose(.) called." << endl;
     12        return ost;
    1313};
    1414
     
    3535        int bits = 1, counter = 1;
    3636        while ((bits = 1 << counter) < BinaryNumber)
    37     counter++;
    38   for (int i=0;i<counter-1;i++) {
    39         if ((BinaryNumber & (1 << i)) == 0)
    40                 ost.put('0');
     37                counter++;
     38        for (int i=0;i<counter-1;i++) {
     39                if ((BinaryNumber & (1 << i)) == 0)
     40                        ost.put('0');
    4141                else
    42                 ost.put('1');
    43   }
    44   ost.put('b');
    45   //cout << "Binary(.) called." << endl;
    46   return ost;
     42                        ost.put('1');
     43        }
     44        ost.put('b');
     45        //cout << "Binary(.) called." << endl;
     46        return ost;
    4747};
    4848
Note: See TracChangeset for help on using the changeset viewer.