Changeset 437922


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

Fix indentation from tab to two spaces.

The trouble was caused at the merge e08f45e4539ffcc30e039dec5606cf06b45ab6be. Seemingly, I thought eclipse had pulled some shit which i didn't

Location:
src
Files:
16 edited

Legend:

Unmodified
Added
Removed
  • src/analyzer.cpp

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

    r178f92 r437922  
    1313atom::atom()
    1414{
    15         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;
     15  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;
    3131};
    3232
     
    3535atom::~atom()
    3636{
    37         Free((void **)&Name, "atom::~atom: *Name");
    38         Free((void **)&ComponentNr, "atom::~atom: *ComponentNr");
     37  Free((void **)&Name, "atom::~atom: *Name");
     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
     
    6262bool atom::Output(int ElementNo, int AtomNo, ofstream *out, const char *comment) const
    6363{
    64         if (out != NULL) {
    65                 *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t"        << fixed << setprecision(9) << showpoint;
    66                 *out << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2];
    67                 *out << "\t" << FixedIon;
    68                 if (v.Norm() > MYEPSILON)
    69                         *out << "\t" << scientific << setprecision(6) << v.x[0] << "\t" << v.x[1] << "\t" << v.x[2] << "\t";
    70                 if (comment != NULL)
    71                   *out << " # " << comment << endl;
    72                 else
    73                   *out << " # molecule nr " << nr << endl;
    74                 return true;
    75         } else
    76                 return false;
     64  if (out != NULL) {
     65    *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t"  << fixed << setprecision(9) << showpoint;
     66    *out << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2];
     67    *out << "\t" << FixedIon;
     68    if (v.Norm() > MYEPSILON)
     69      *out << "\t" << scientific << setprecision(6) << v.x[0] << "\t" << v.x[1] << "\t" << v.x[2] << "\t";
     70    if (comment != NULL)
     71      *out << " # " << comment << endl;
     72    else
     73      *out << " # molecule nr " << nr << endl;
     74    return true;
     75  } else
     76    return false;
    7777};
    7878
     
    8282bool atom::OutputXYZLine(ofstream *out) const
    8383{
    84         if (out != NULL) {
    85                 *out << type->symbol << "\t" << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2] << "\t" << endl;
    86                 return true;
    87         } else
    88                 return false;
     84  if (out != NULL) {
     85    *out << type->symbol << "\t" << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2] << "\t" << endl;
     86    return true;
     87  } else
     88    return false;
    8989};
    9090
    9191ostream & operator << (ostream &ost, atom &a)
    9292{
    93         ost << "[" << a.Name << "|" << &a << "]";
    94         return ost;
     93  ost << "[" << a.Name << "|" << &a << "]";
     94  return ost;
    9595};
    9696
     
    101101bool atom::Compare(atom &ptr)
    102102{
    103         if (nr < ptr.nr)
    104                 return true;
    105         else
    106                 return false;
     103  if (nr < ptr.nr)
     104    return true;
     105  else
     106    return false;
    107107};
    108108
    109109bool operator < (atom &a, atom &b)
    110110{
    111         return a.Compare(b);
     111  return a.Compare(b);
    112112};
    113113
  • src/bond.cpp

    r178f92 r437922  
    1414bond::bond()
    1515{
    16         leftatom = NULL;
    17         rightatom = NULL;
    18         previous = NULL;
    19         next = NULL;
    20         nr = -1;
    21         HydrogenBond = 0;
    22         BondDegree = 0;
    23         Used = white;
    24         Cyclic = false;
    25         Type = Undetermined;
     16  leftatom = NULL;
     17  rightatom = NULL;
     18  previous = NULL;
     19  next = NULL;
     20  nr = -1;
     21  HydrogenBond = 0;
     22  BondDegree = 0;
     23  Used = white;
     24  Cyclic = false;
     25  Type = Undetermined;
    2626};
    2727
     
    3434bond::bond(atom *left, atom *right, int degree=1, int number=0)
    3535{
    36         leftatom = left;
    37         rightatom = right;
    38         previous = NULL;
    39         next = NULL;
    40         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;
     36  leftatom = left;
     37  rightatom = right;
     38  previous = NULL;
     39  next = NULL;
     40  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;
    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

    r178f92 r437922  
    1515BoundaryPointSet::BoundaryPointSet()
    1616{
    17         LinesCount = 0;
    18         Nr = -1;
     17  LinesCount = 0;
     18  Nr = -1;
    1919}
    2020;
     
    2222BoundaryPointSet::BoundaryPointSet(atom *Walker)
    2323{
    24         node = Walker;
    25         LinesCount = 0;
    26         Nr = Walker->nr;
     24  node = Walker;
     25  LinesCount = 0;
     26  Nr = Walker->nr;
    2727}
    2828;
     
    3030BoundaryPointSet::~BoundaryPointSet()
    3131{
    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;
     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;
    3636}
    3737;
     
    3939void BoundaryPointSet::AddLine(class BoundaryLineSet *line)
    4040{
    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++;
     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++;
    5252}
    5353;
     
    5656operator <<(ostream &ost, BoundaryPointSet &a)
    5757{
    58         ost << "[" << a.Nr << "|" << a.node->Name << "]";
    59         return ost;
     58  ost << "[" << a.Nr << "|" << a.node->Name << "]";
     59  return ost;
    6060}
    6161;
     
    6565BoundaryLineSet::BoundaryLineSet()
    6666{
    67         for (int i = 0; i < 2; i++)
    68                 endpoints[i] = NULL;
    69         TrianglesCount = 0;
    70         Nr = -1;
     67  for (int i = 0; i < 2; i++)
     68    endpoints[i] = NULL;
     69  TrianglesCount = 0;
     70  Nr = -1;
    7171}
    7272;
     
    7474BoundaryLineSet::BoundaryLineSet(class BoundaryPointSet *Point[2], int number)
    7575{
    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;
     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;
    8686}
    8787;
     
    8989BoundaryLineSet::~BoundaryLineSet()
    9090{
    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;
     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;
    109109}
    110110;
     
    113113BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle)
    114114{
    115         cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "."
    116                         << endl;
    117         triangles.insert(TrianglePair(triangle->Nr, triangle));
    118         TrianglesCount++;
     115  cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "."
     116      << endl;
     117  triangles.insert(TrianglePair(triangle->Nr, triangle));
     118  TrianglesCount++;
    119119}
    120120;
     
    123123operator <<(ostream &ost, BoundaryLineSet &a)
    124124{
    125         ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","
    126                         << a.endpoints[1]->node->Name << "]";
    127         return ost;
     125  ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","
     126      << a.endpoints[1]->node->Name << "]";
     127  return ost;
    128128}
    129129;
     
    134134BoundaryTriangleSet::BoundaryTriangleSet()
    135135{
    136         for (int i = 0; i < 3; i++)
    137                 {
    138                         endpoints[i] = NULL;
    139                         lines[i] = NULL;
    140                 }
    141         Nr = -1;
     136  for (int i = 0; i < 3; i++)
     137    {
     138      endpoints[i] = NULL;
     139      lines[i] = NULL;
     140    }
     141  Nr = -1;
    142142}
    143143;
    144144
    145145BoundaryTriangleSet::BoundaryTriangleSet(class BoundaryLineSet *line[3],
    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;
     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;
    184184}
    185185;
     
    187187BoundaryTriangleSet::~BoundaryTriangleSet()
    188188{
    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         }
     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  }
    202202}
    203203;
     
    206206BoundaryTriangleSet::GetNormalVector(Vector &OtherVector)
    207207{
    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.);
     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.);
    215215}
    216216;
     
    219219operator <<(ostream &ost, BoundaryTriangleSet &a)
    220220{
    221         ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","
    222                         << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]";
    223         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;
    224224}
    225225;
     
    235235GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2)
    236236{
    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;
     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;
    259259}
    260260;
     
    270270GetBoundaryPoints(ofstream *out, molecule *mol)
    271271{
    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;
     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;
    467467}
    468468;
     
    478478double *
    479479GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol,
    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;
     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;
    570570}
    571571;
     
    579579void write_vrml_file(ofstream *out, ofstream *vrmlfile, class Tesselation *Tess, class molecule *mol)
    580580{
    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);
     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);
    625625};
    626626
     
    633633void write_raster3d_file(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, class molecule *mol)
    634634{
    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);
     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);
    681681};
    682682
     
    688688void
    689689write_tecplot_file(ofstream *out, ofstream *tecplot,
    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                 }
     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    }
    732732}
    733733
     
    743743double
    744744VolumeOfConvexEnvelope(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;
     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;
    872872}
    873873;
     
    883883void
    884884PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol,
    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;
     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;
    993993}
    994994;
     
    10001000Tesselation::Tesselation()
    10011001{
    1002         PointsOnBoundaryCount = 0;
    1003         LinesOnBoundaryCount = 0;
    1004         TrianglesOnBoundaryCount = 0;
    1005         TriangleFilesWritten = 0;
     1002  PointsOnBoundaryCount = 0;
     1003  LinesOnBoundaryCount = 0;
     1004  TrianglesOnBoundaryCount = 0;
     1005  TriangleFilesWritten = 0;
    10061006}
    10071007;
     
    10121012Tesselation::~Tesselation()
    10131013{
    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         }
     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  }
    10221022}
    10231023;
     
    10311031Tesselation::GuessStartingTriangle(ofstream *out)
    10321032{
    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                 }
     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    }
    11851185}
    11861186;
     
    11911191 * -# if the lines contains to only one triangle
    11921192 * -# We search all points in the boundary
    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)
     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)
    11971197 * \param *out output stream for debugging
    11981198 * \param *configuration for IsAngstroem
     
    12011201void
    12021202Tesselation::TesselateOnBoundary(ofstream *out, config *configuration,
    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);
     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);
    14231423
    14241424}
     
    14311431Tesselation::AddPoint(atom *Walker)
    14321432{
    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++;
     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++;
    14381438}
    14391439;
     
    14471447Tesselation::AddTrianglePoint(atom* Candidate, int n)
    14481448{
    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                 }
     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    }
    14631463}
    14641464;
     
    14731473void
    14741474Tesselation::AddTriangleLine(class BoundaryPointSet *a,
    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                 }
     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    }
    15121512}
    15131513;
     
    15201520{
    15211521
    1522         cout << Verbose(1) << "Adding triangle to its lines" << endl;
    1523         TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
    1524         TrianglesOnBoundaryCount++;
    1525 
    1526         /*
    1527         * this is apparently done when constructing triangle
    1528 
    1529         for (i=0; i<3; i++)
    1530         {
    1531         BLS[i]->AddTriangle(BTS);
    1532         }
    1533         */
     1522  cout << Verbose(1) << "Adding triangle to its lines" << endl;
     1523  TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
     1524  TrianglesOnBoundaryCount++;
     1525
     1526  /*
     1527  * this is apparently done when constructing triangle
     1528
     1529  for (i=0; i<3; i++)
     1530  {
     1531  BLS[i]->AddTriangle(BTS);
     1532  }
     1533  */
    15341534}
    15351535;
     
    15371537
    15381538double det_get(gsl_matrix *A, int inPlace) {
    1539         /*
    1540         inPlace = 1 => A is replaced with the LU decomposed copy.
    1541         inPlace = 0 => A is retained, and a copy is used for LU.
    1542         */
    1543 
    1544         double det;
    1545         int signum;
    1546         gsl_permutation *p = gsl_permutation_alloc(A->size1);
    1547         gsl_matrix *tmpA;
    1548 
    1549         if (inPlace)
    1550         tmpA = A;
    1551         else {
    1552         gsl_matrix *tmpA = gsl_matrix_alloc(A->size1, A->size2);
    1553         gsl_matrix_memcpy(tmpA , A);
    1554         }
    1555 
    1556 
    1557         gsl_linalg_LU_decomp(tmpA , p , &signum);
    1558         det = gsl_linalg_LU_det(tmpA , signum);
    1559         gsl_permutation_free(p);
    1560         if (! inPlace)
    1561         gsl_matrix_free(tmpA);
    1562 
    1563         return det;
     1539  /*
     1540  inPlace = 1 => A is replaced with the LU decomposed copy.
     1541  inPlace = 0 => A is retained, and a copy is used for LU.
     1542  */
     1543
     1544  double det;
     1545  int signum;
     1546  gsl_permutation *p = gsl_permutation_alloc(A->size1);
     1547  gsl_matrix *tmpA;
     1548
     1549  if (inPlace)
     1550  tmpA = A;
     1551  else {
     1552  gsl_matrix *tmpA = gsl_matrix_alloc(A->size1, A->size2);
     1553  gsl_matrix_memcpy(tmpA , A);
     1554  }
     1555
     1556
     1557  gsl_linalg_LU_decomp(tmpA , p , &signum);
     1558  det = gsl_linalg_LU_det(tmpA , signum);
     1559  gsl_permutation_free(p);
     1560  if (! inPlace)
     1561  gsl_matrix_free(tmpA);
     1562
     1563  return det;
    15641564};
    15651565
    15661566void get_sphere(Vector *center, Vector &a, Vector &b, Vector &c, double RADIUS)
    15671567{
    1568         gsl_matrix *A = gsl_matrix_calloc(3,3);
    1569         double m11, m12, m13, m14;
    1570 
    1571         for(int i=0;i<3;i++) {
    1572                 gsl_matrix_set(A, i, 0, a.x[i]);
    1573                 gsl_matrix_set(A, i, 1, b.x[i]);
    1574                 gsl_matrix_set(A, i, 2, c.x[i]);
    1575         }
    1576         m11 = det_get(A, 1);
    1577 
    1578         for(int i=0;i<3;i++) {
    1579                 gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
    1580                 gsl_matrix_set(A, i, 1, b.x[i]);
    1581                 gsl_matrix_set(A, i, 2, c.x[i]);
    1582         }
    1583         m12 = det_get(A, 1);
    1584 
    1585         for(int i=0;i<3;i++) {
    1586                 gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
    1587                 gsl_matrix_set(A, i, 1, a.x[i]);
    1588                 gsl_matrix_set(A, i, 2, c.x[i]);
    1589         }
    1590         m13 = det_get(A, 1);
    1591 
    1592         for(int i=0;i<3;i++) {
    1593                 gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
    1594                 gsl_matrix_set(A, i, 1, a.x[i]);
    1595                 gsl_matrix_set(A, i, 2, b.x[i]);
    1596         }
    1597         m14 = det_get(A, 1);
    1598 
    1599         if (fabs(m11) < MYEPSILON)
    1600                 cerr << "ERROR: three points are colinear." << endl;
    1601 
    1602         center->x[0] =  0.5 * m12/ m11;
    1603         center->x[1] = -0.5 * m13/ m11;
    1604         center->x[2] =  0.5 * m14/ m11;
    1605 
    1606         if (fabs(a.Distance(center) - RADIUS) > MYEPSILON)
    1607                 cerr << "ERROR: The given center is further way by " << fabs(a.Distance(center) - RADIUS) << " from a than RADIUS." << endl;
    1608 
    1609         gsl_matrix_free(A);
     1568  gsl_matrix *A = gsl_matrix_calloc(3,3);
     1569  double m11, m12, m13, m14;
     1570
     1571  for(int i=0;i<3;i++) {
     1572    gsl_matrix_set(A, i, 0, a.x[i]);
     1573    gsl_matrix_set(A, i, 1, b.x[i]);
     1574    gsl_matrix_set(A, i, 2, c.x[i]);
     1575  }
     1576  m11 = det_get(A, 1);
     1577
     1578  for(int i=0;i<3;i++) {
     1579    gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
     1580    gsl_matrix_set(A, i, 1, b.x[i]);
     1581    gsl_matrix_set(A, i, 2, c.x[i]);
     1582  }
     1583  m12 = det_get(A, 1);
     1584
     1585  for(int i=0;i<3;i++) {
     1586    gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
     1587    gsl_matrix_set(A, i, 1, a.x[i]);
     1588    gsl_matrix_set(A, i, 2, c.x[i]);
     1589  }
     1590  m13 = det_get(A, 1);
     1591
     1592  for(int i=0;i<3;i++) {
     1593    gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
     1594    gsl_matrix_set(A, i, 1, a.x[i]);
     1595    gsl_matrix_set(A, i, 2, b.x[i]);
     1596  }
     1597  m14 = det_get(A, 1);
     1598
     1599  if (fabs(m11) < MYEPSILON)
     1600    cerr << "ERROR: three points are colinear." << endl;
     1601
     1602  center->x[0] =  0.5 * m12/ m11;
     1603  center->x[1] = -0.5 * m13/ m11;
     1604  center->x[2] =  0.5 * m14/ m11;
     1605
     1606  if (fabs(a.Distance(center) - RADIUS) > MYEPSILON)
     1607    cerr << "ERROR: The given center is further way by " << fabs(a.Distance(center) - RADIUS) << " from a than RADIUS." << endl;
     1608
     1609  gsl_matrix_free(A);
    16101610};
    16111611
     
    16291629 */
    16301630void Get_center_of_sphere(Vector* Center, Vector a, Vector b, Vector c, Vector *NewUmkreismittelpunkt, Vector* Direction, Vector* AlternativeDirection,
    1631                 double HalfplaneIndicator, double AlternativeIndicator, double alpha, double beta, double gamma, double RADIUS, double Umkreisradius)
    1632 {
    1633         Vector TempNormal, helper;
    1634         double Restradius;
    1635         Vector OtherCenter;
    1636         cout << Verbose(3) << "Begin of Get_center_of_sphere.\n";
    1637         Center->Zero();
    1638         helper.CopyVector(&a);
    1639         helper.Scale(sin(2.*alpha));
    1640         Center->AddVector(&helper);
    1641         helper.CopyVector(&b);
    1642         helper.Scale(sin(2.*beta));
    1643         Center->AddVector(&helper);
    1644         helper.CopyVector(&c);
    1645         helper.Scale(sin(2.*gamma));
    1646         Center->AddVector(&helper);
    1647         //*Center = a * sin(2.*alpha) + b * sin(2.*beta) + c * sin(2.*gamma) ;
    1648         Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));
    1649         NewUmkreismittelpunkt->CopyVector(Center);
    1650         cout << Verbose(4) << "Center of new circumference is " << *NewUmkreismittelpunkt << ".\n";
    1651         // Here we calculated center of circumscribing circle, using barycentric coordinates
    1652         cout << Verbose(4) << "Center of circumference is " << *Center << " in direction " << *Direction << ".\n";
    1653 
    1654         TempNormal.CopyVector(&a);
    1655         TempNormal.SubtractVector(&b);
    1656         helper.CopyVector(&a);
    1657         helper.SubtractVector(&c);
    1658         TempNormal.VectorProduct(&helper);
    1659         if (fabs(HalfplaneIndicator) < MYEPSILON)
    1660                 {
    1661                         if ((TempNormal.ScalarProduct(AlternativeDirection) <0 and AlternativeIndicator >0) or (TempNormal.ScalarProduct(AlternativeDirection) >0 and AlternativeIndicator <0))
    1662                                 {
    1663                                         TempNormal.Scale(-1);
    1664                                 }
    1665                 }
    1666         else
    1667                 {
    1668                         if (TempNormal.ScalarProduct(Direction)<0 && HalfplaneIndicator >0 || TempNormal.ScalarProduct(Direction)>0 && HalfplaneIndicator<0)
    1669                                 {
    1670                                         TempNormal.Scale(-1);
    1671                                 }
    1672                 }
    1673 
    1674         TempNormal.Normalize();
    1675         Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius);
    1676         cout << Verbose(4) << "Height of center of circumference to center of sphere is " << Restradius << ".\n";
    1677         TempNormal.Scale(Restradius);
    1678         cout << Verbose(4) << "Shift vector to sphere of circumference is " << TempNormal << ".\n";
    1679 
    1680         Center->AddVector(&TempNormal);
    1681         cout << Verbose(0) << "Center of sphere of circumference is " << *Center << ".\n";
    1682         get_sphere(&OtherCenter, a, b, c, RADIUS);
    1683         cout << Verbose(0) << "OtherCenter of sphere of circumference is " << OtherCenter << ".\n";
    1684         cout << Verbose(3) << "End of Get_center_of_sphere.\n";
     1631    double HalfplaneIndicator, double AlternativeIndicator, double alpha, double beta, double gamma, double RADIUS, double Umkreisradius)
     1632{
     1633  Vector TempNormal, helper;
     1634  double Restradius;
     1635  Vector OtherCenter;
     1636  cout << Verbose(3) << "Begin of Get_center_of_sphere.\n";
     1637  Center->Zero();
     1638  helper.CopyVector(&a);
     1639  helper.Scale(sin(2.*alpha));
     1640  Center->AddVector(&helper);
     1641  helper.CopyVector(&b);
     1642  helper.Scale(sin(2.*beta));
     1643  Center->AddVector(&helper);
     1644  helper.CopyVector(&c);
     1645  helper.Scale(sin(2.*gamma));
     1646  Center->AddVector(&helper);
     1647  //*Center = a * sin(2.*alpha) + b * sin(2.*beta) + c * sin(2.*gamma) ;
     1648  Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));
     1649  NewUmkreismittelpunkt->CopyVector(Center);
     1650  cout << Verbose(4) << "Center of new circumference is " << *NewUmkreismittelpunkt << ".\n";
     1651  // Here we calculated center of circumscribing circle, using barycentric coordinates
     1652  cout << Verbose(4) << "Center of circumference is " << *Center << " in direction " << *Direction << ".\n";
     1653
     1654  TempNormal.CopyVector(&a);
     1655  TempNormal.SubtractVector(&b);
     1656  helper.CopyVector(&a);
     1657  helper.SubtractVector(&c);
     1658  TempNormal.VectorProduct(&helper);
     1659  if (fabs(HalfplaneIndicator) < MYEPSILON)
     1660    {
     1661      if ((TempNormal.ScalarProduct(AlternativeDirection) <0 and AlternativeIndicator >0) or (TempNormal.ScalarProduct(AlternativeDirection) >0 and AlternativeIndicator <0))
     1662        {
     1663          TempNormal.Scale(-1);
     1664        }
     1665    }
     1666  else
     1667    {
     1668      if (TempNormal.ScalarProduct(Direction)<0 && HalfplaneIndicator >0 || TempNormal.ScalarProduct(Direction)>0 && HalfplaneIndicator<0)
     1669        {
     1670          TempNormal.Scale(-1);
     1671        }
     1672    }
     1673
     1674  TempNormal.Normalize();
     1675  Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius);
     1676  cout << Verbose(4) << "Height of center of circumference to center of sphere is " << Restradius << ".\n";
     1677  TempNormal.Scale(Restradius);
     1678  cout << Verbose(4) << "Shift vector to sphere of circumference is " << TempNormal << ".\n";
     1679
     1680  Center->AddVector(&TempNormal);
     1681  cout << Verbose(0) << "Center of sphere of circumference is " << *Center << ".\n";
     1682  get_sphere(&OtherCenter, a, b, c, RADIUS);
     1683  cout << Verbose(0) << "OtherCenter of sphere of circumference is " << OtherCenter << ".\n";
     1684  cout << Verbose(3) << "End of Get_center_of_sphere.\n";
    16851685};
    16861686
    16871687/** This recursive function finds a third point, to form a triangle with two given ones.
    16881688 * Two atoms are fixed, a candidate is supplied, additionally two vectors for direction distinction, a Storage area to \
    1689  *      supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \
    1690  *      upon which we operate.
    1691  *      If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \
    1692  *      direction and angle into Storage.
    1693  *      We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \
    1694  *      with all neighbours of the candidate.
     1689 *  supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \
     1690 *  upon which we operate.
     1691 *  If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \
     1692 *  direction and angle into Storage.
     1693 *  We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \
     1694 *  with all neighbours of the candidate.
    16951695 * @param a first point
    16961696 * @param b second point
     
    17091709 */
    17101710void Tesselation::Find_next_suitable_point_via_Angle_of_Sphere(atom* a, atom* b, atom* c, atom* Candidate, atom* Parent,
    1711                 int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint,
    1712                 atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol)
    1713 {
    1714         cout << Verbose(2) << "Begin of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n";
    1715         cout << Verbose(3) << "Candidate is "<< *Candidate << endl;
    1716         cout << Verbose(4) << "Baseline vector is " << *Chord << "." << endl;
    1717         cout << Verbose(4) << "ReferencePoint is " << ReferencePoint << "." << endl;
    1718         cout << Verbose(4) << "Normal of base triangle is " << *OldNormal << "." << endl;
    1719         cout << Verbose(4) << "Search direction is " << *direction1 << "." << endl;
    1720         /* OldNormal is normal vector on the old triangle
    1721         * direction1 is normal on the triangle line, from which we come, as well as on OldNormal.
    1722         * Chord points from b to a!!!
    1723         */
    1724         Vector dif_a; //Vector from a to candidate
    1725         Vector dif_b; //Vector from b to candidate
    1726         Vector AngleCheck;
    1727         Vector TempNormal, Umkreismittelpunkt;
    1728         Vector Mittelpunkt;
    1729 
    1730         double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius;
    1731         double BallAngle, AlternativeSign;
    1732         atom *Walker; // variable atom point
    1733 
    1734         Vector NewUmkreismittelpunkt;
    1735 
    1736         if (a != Candidate and b != Candidate and c != Candidate) {
    1737                 cout << Verbose(3) << "We have a unique candidate!" << endl;
    1738                 dif_a.CopyVector(&(a->x));
    1739                 dif_a.SubtractVector(&(Candidate->x));
    1740                 dif_b.CopyVector(&(b->x));
    1741                 dif_b.SubtractVector(&(Candidate->x));
    1742                 AngleCheck.CopyVector(&(Candidate->x));
    1743                 AngleCheck.SubtractVector(&(a->x));
    1744                 AngleCheck.ProjectOntoPlane(Chord);
    1745 
    1746                 SideA = dif_b.Norm();
    1747                 SideB = dif_a.Norm();
    1748                 SideC = Chord->Norm();
    1749                 //Chord->Scale(-1);
    1750 
    1751                 alpha = Chord->Angle(&dif_a);
    1752                 beta = M_PI - Chord->Angle(&dif_b);
    1753                 gamma = dif_a.Angle(&dif_b);
    1754 
    1755                 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;
    1756 
    1757                 if (fabs(M_PI - alpha - beta - gamma) > MYEPSILON) {
    1758                         cerr << Verbose(0) << "WARNING: sum of angles for base triangle " << (alpha + beta + gamma)/M_PI*180. << " != 180.\n";
    1759                         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;
    1760                 }
    1761 
    1762                 if ((M_PI*179./180. > alpha) && (M_PI*179./180. > beta) && (M_PI*179./180. > gamma)) {
    1763                         Umkreisradius = SideA / 2.0 / sin(alpha);
    1764                         //cout << Umkreisradius << endl;
    1765                         //cout << SideB / 2.0 / sin(beta) << endl;
    1766                         //cout << SideC / 2.0 / sin(gamma) << endl;
    1767 
    1768                         if (Umkreisradius < RADIUS) { //Checking whether ball will at least rest on points.
    1769                                 cout << Verbose(3) << "Circle of circumference would fit: " << Umkreisradius << " < " << RADIUS << "." << endl;
    1770                                 cout << Verbose(2) << "Candidate is "<< *Candidate << endl;
    1771                                 sign = AngleCheck.ScalarProduct(direction1);
    1772                                 if (fabs(sign)<MYEPSILON) {
    1773                                         if (AngleCheck.ScalarProduct(OldNormal)<0) {
    1774                                                 sign =0;
    1775                                                 AlternativeSign=1;
    1776                                         } else {
    1777                                                 sign =0;
    1778                                                 AlternativeSign=-1;
    1779                                         }
    1780                                 } else {
    1781                                         sign /= fabs(sign);
    1782                                 }
    1783                                 if (sign >= 0) {
    1784                                         cout << Verbose(3) << "Candidate is in search direction: " << sign << "." << endl;
    1785                                         Get_center_of_sphere(&Mittelpunkt, (a->x), (b->x), (Candidate->x), &NewUmkreismittelpunkt, OldNormal, direction1, sign, AlternativeSign, alpha, beta, gamma, RADIUS, Umkreisradius);
    1786                                         Mittelpunkt.SubtractVector(&ReferencePoint);
    1787                                         cout << Verbose(3) << "Reference vector to sphere's center is " << Mittelpunkt << "." << endl;
    1788                                         BallAngle = Mittelpunkt.Angle(OldNormal);
    1789                                         cout << Verbose(3) << "Angle between normal of base triangle and center of ball sphere is :" << BallAngle << "." << endl;
    1790 
    1791                                         //cout << "direction1 is " << *direction1 << "." << endl;
    1792                                         //cout << "Mittelpunkt is " << Mittelpunkt << "."<< endl;
    1793                                         //cout << Verbose(3) << "BallAngle is " << BallAngle << " Sign is " << sign << endl;
    1794 
    1795                                         NewUmkreismittelpunkt.SubtractVector(&ReferencePoint);
    1796 
    1797                                         if ((Mittelpunkt.ScalarProduct(direction1) >=0) || (fabs(NewUmkreismittelpunkt.Norm()) < MYEPSILON)) {
    1798                                                 if (Storage[0]< -1.5) { // first Candidate at all
    1799                                                         if (1) {//if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) {
    1800                                                                 cout << Verbose(2) << "First good candidate is " << *Candidate << " with ";
    1801                                                                 Opt_Candidate = Candidate;
    1802                                                                 Storage[0] = sign;
    1803                                                                 Storage[1] = AlternativeSign;
    1804                                                                 Storage[2] = BallAngle;
    1805                                                                 cout << " angle " << Storage[2] << " and Up/Down " << Storage[0] << endl;
    1806                                                         } else
    1807                                                                 cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl;
    1808                                                 } else {
    1809                                                         if ( Storage[2] > BallAngle) {
    1810                                                                 if (1) { //if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) {
    1811                                                                         cout << Verbose(2) << "Next better candidate is " << *Candidate << " with ";
    1812                                                                         Opt_Candidate = Candidate;
    1813                                                                         Storage[0] = sign;
    1814                                                                         Storage[1] = AlternativeSign;
    1815                                                                         Storage[2] = BallAngle;
    1816                                                                         cout << " angle " << Storage[2] << " and Up/Down " << Storage[0] << endl;
    1817                                                                 } else
    1818                                                                         cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl;
    1819                                                         } else {
    1820                                                                 if (DEBUG) {
    1821                                                                         cout << Verbose(3) << *Candidate << " looses against better candidate " << *Opt_Candidate << "." << endl;
    1822                                                                 }
    1823                                                         }
    1824                                                 }
    1825                                         } else {
    1826                                                 if (DEBUG) {
    1827                                                         cout << Verbose(3) << *Candidate << " refused due to Up/Down sign which is " << sign << endl;
    1828                                                 }
    1829                                         }
    1830                                 } else {
    1831                                         if (DEBUG) {
    1832                                                 cout << Verbose(3) << *Candidate << " is not in search direction." << endl;
    1833                                         }
    1834                                 }
    1835                         } else {
    1836                                 if (DEBUG) {
    1837                                         cout << Verbose(3) << *Candidate << " would have circumference of " << Umkreisradius << " bigger than ball's radius " << RADIUS << "." << endl;
    1838                                 }
    1839                         }
    1840                 } else {
    1841                         if (DEBUG) {
    1842                                 cout << Verbose(0) << "Triangle consisting of " << *Candidate << ", " << *a << " and " << *b << " has an angle >150!" << endl;
    1843                         }
    1844                 }
    1845         } else {
    1846                 if (DEBUG) {
    1847                         cout << Verbose(3) << *Candidate << " is either " << *a << " or " << *b << "." << endl;
    1848                 }
    1849         }
    1850 
    1851         if (RecursionLevel < 5) { // Seven is the recursion level threshold.
    1852                 for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) { // go through all bond
    1853                         Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate);
    1854                         if (Walker == Parent) { // don't go back the same bond
    1855                                 continue;
    1856                         } else {
    1857                                 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
    1858                         }
    1859                 }
    1860         }
    1861         cout << Verbose(2) << "End of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n";
     1711    int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint,
     1712    atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol)
     1713{
     1714  cout << Verbose(2) << "Begin of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n";
     1715  cout << Verbose(3) << "Candidate is "<< *Candidate << endl;
     1716  cout << Verbose(4) << "Baseline vector is " << *Chord << "." << endl;
     1717  cout << Verbose(4) << "ReferencePoint is " << ReferencePoint << "." << endl;
     1718  cout << Verbose(4) << "Normal of base triangle is " << *OldNormal << "." << endl;
     1719  cout << Verbose(4) << "Search direction is " << *direction1 << "." << endl;
     1720  /* OldNormal is normal vector on the old triangle
     1721  * direction1 is normal on the triangle line, from which we come, as well as on OldNormal.
     1722  * Chord points from b to a!!!
     1723  */
     1724  Vector dif_a; //Vector from a to candidate
     1725  Vector dif_b; //Vector from b to candidate
     1726  Vector AngleCheck;
     1727  Vector TempNormal, Umkreismittelpunkt;
     1728  Vector Mittelpunkt;
     1729
     1730  double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius;
     1731  double BallAngle, AlternativeSign;
     1732  atom *Walker; // variable atom point
     1733
     1734  Vector NewUmkreismittelpunkt;
     1735
     1736  if (a != Candidate and b != Candidate and c != Candidate) {
     1737    cout << Verbose(3) << "We have a unique candidate!" << endl;
     1738    dif_a.CopyVector(&(a->x));
     1739    dif_a.SubtractVector(&(Candidate->x));
     1740    dif_b.CopyVector(&(b->x));
     1741    dif_b.SubtractVector(&(Candidate->x));
     1742    AngleCheck.CopyVector(&(Candidate->x));
     1743    AngleCheck.SubtractVector(&(a->x));
     1744    AngleCheck.ProjectOntoPlane(Chord);
     1745
     1746    SideA = dif_b.Norm();
     1747    SideB = dif_a.Norm();
     1748    SideC = Chord->Norm();
     1749    //Chord->Scale(-1);
     1750
     1751    alpha = Chord->Angle(&dif_a);
     1752    beta = M_PI - Chord->Angle(&dif_b);
     1753    gamma = dif_a.Angle(&dif_b);
     1754
     1755    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;
     1756
     1757    if (fabs(M_PI - alpha - beta - gamma) > MYEPSILON) {
     1758      cerr << Verbose(0) << "WARNING: sum of angles for base triangle " << (alpha + beta + gamma)/M_PI*180. << " != 180.\n";
     1759      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;
     1760    }
     1761
     1762    if ((M_PI*179./180. > alpha) && (M_PI*179./180. > beta) && (M_PI*179./180. > gamma)) {
     1763      Umkreisradius = SideA / 2.0 / sin(alpha);
     1764      //cout << Umkreisradius << endl;
     1765      //cout << SideB / 2.0 / sin(beta) << endl;
     1766      //cout << SideC / 2.0 / sin(gamma) << endl;
     1767
     1768      if (Umkreisradius < RADIUS) { //Checking whether ball will at least rest on points.
     1769        cout << Verbose(3) << "Circle of circumference would fit: " << Umkreisradius << " < " << RADIUS << "." << endl;
     1770        cout << Verbose(2) << "Candidate is "<< *Candidate << endl;
     1771        sign = AngleCheck.ScalarProduct(direction1);
     1772        if (fabs(sign)<MYEPSILON) {
     1773          if (AngleCheck.ScalarProduct(OldNormal)<0) {
     1774            sign =0;
     1775            AlternativeSign=1;
     1776          } else {
     1777            sign =0;
     1778            AlternativeSign=-1;
     1779          }
     1780        } else {
     1781          sign /= fabs(sign);
     1782        }
     1783        if (sign >= 0) {
     1784          cout << Verbose(3) << "Candidate is in search direction: " << sign << "." << endl;
     1785          Get_center_of_sphere(&Mittelpunkt, (a->x), (b->x), (Candidate->x), &NewUmkreismittelpunkt, OldNormal, direction1, sign, AlternativeSign, alpha, beta, gamma, RADIUS, Umkreisradius);
     1786          Mittelpunkt.SubtractVector(&ReferencePoint);
     1787          cout << Verbose(3) << "Reference vector to sphere's center is " << Mittelpunkt << "." << endl;
     1788          BallAngle = Mittelpunkt.Angle(OldNormal);
     1789          cout << Verbose(3) << "Angle between normal of base triangle and center of ball sphere is :" << BallAngle << "." << endl;
     1790
     1791          //cout << "direction1 is " << *direction1 << "." << endl;
     1792          //cout << "Mittelpunkt is " << Mittelpunkt << "."<< endl;
     1793          //cout << Verbose(3) << "BallAngle is " << BallAngle << " Sign is " << sign << endl;
     1794
     1795          NewUmkreismittelpunkt.SubtractVector(&ReferencePoint);
     1796
     1797          if ((Mittelpunkt.ScalarProduct(direction1) >=0) || (fabs(NewUmkreismittelpunkt.Norm()) < MYEPSILON)) {
     1798            if (Storage[0]< -1.5) { // first Candidate at all
     1799              if (1) {//if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) {
     1800                cout << Verbose(2) << "First good candidate is " << *Candidate << " with ";
     1801                Opt_Candidate = Candidate;
     1802                Storage[0] = sign;
     1803                Storage[1] = AlternativeSign;
     1804                Storage[2] = BallAngle;
     1805                cout << " angle " << Storage[2] << " and Up/Down " << Storage[0] << endl;
     1806              } else
     1807                cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl;
     1808            } else {
     1809              if ( Storage[2] > BallAngle) {
     1810                if (1) { //if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) {
     1811                  cout << Verbose(2) << "Next better candidate is " << *Candidate << " with ";
     1812                  Opt_Candidate = Candidate;
     1813                  Storage[0] = sign;
     1814                  Storage[1] = AlternativeSign;
     1815                  Storage[2] = BallAngle;
     1816                  cout << " angle " << Storage[2] << " and Up/Down " << Storage[0] << endl;
     1817                } else
     1818                  cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl;
     1819              } else {
     1820                if (DEBUG) {
     1821                  cout << Verbose(3) << *Candidate << " looses against better candidate " << *Opt_Candidate << "." << endl;
     1822                }
     1823              }
     1824            }
     1825          } else {
     1826            if (DEBUG) {
     1827              cout << Verbose(3) << *Candidate << " refused due to Up/Down sign which is " << sign << endl;
     1828            }
     1829          }
     1830        } else {
     1831          if (DEBUG) {
     1832            cout << Verbose(3) << *Candidate << " is not in search direction." << endl;
     1833          }
     1834        }
     1835      } else {
     1836        if (DEBUG) {
     1837          cout << Verbose(3) << *Candidate << " would have circumference of " << Umkreisradius << " bigger than ball's radius " << RADIUS << "." << endl;
     1838        }
     1839      }
     1840    } else {
     1841      if (DEBUG) {
     1842        cout << Verbose(0) << "Triangle consisting of " << *Candidate << ", " << *a << " and " << *b << " has an angle >150!" << endl;
     1843      }
     1844    }
     1845  } else {
     1846    if (DEBUG) {
     1847      cout << Verbose(3) << *Candidate << " is either " << *a << " or " << *b << "." << endl;
     1848    }
     1849  }
     1850
     1851  if (RecursionLevel < 5) { // Seven is the recursion level threshold.
     1852    for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) { // go through all bond
     1853      Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate);
     1854      if (Walker == Parent) { // don't go back the same bond
     1855        continue;
     1856      } else {
     1857        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
     1858      }
     1859    }
     1860  }
     1861  cout << Verbose(2) << "End of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n";
    18621862}
    18631863;
     
    18721872void GetCenterofCircumcircle(Vector *Center, Vector *a, Vector *b, Vector *c)
    18731873{
    1874         Vector helper;
    1875         double alpha, beta, gamma;
    1876         Vector SideA, SideB, SideC;
    1877         SideA.CopyVector(b);
    1878         SideA.SubtractVector(c);
    1879         SideB.CopyVector(c);
    1880         SideB.SubtractVector(a);
    1881         SideC.CopyVector(a);
    1882         SideC.SubtractVector(b);
    1883         alpha = M_PI - SideB.Angle(&SideC);
    1884         beta = M_PI - SideC.Angle(&SideA);
    1885         gamma = M_PI - SideA.Angle(&SideB);
    1886         cout << Verbose(3) << "INFO: alpha = " << alpha/M_PI*180. << ", beta = " << beta/M_PI*180. << ", gamma = " << gamma/M_PI*180. << "." << endl;
    1887         if (fabs(M_PI - alpha - beta - gamma) > HULLEPSILON)
    1888                 cerr << "Sum of angles " << (alpha+beta+gamma)/M_PI*180. << " > 180 degrees by " << fabs(M_PI - alpha - beta - gamma)/M_PI*180. << "!" << endl;
    1889 
    1890         Center->Zero();
    1891         helper.CopyVector(a);
    1892         helper.Scale(sin(2.*alpha));
    1893         Center->AddVector(&helper);
    1894         helper.CopyVector(b);
    1895         helper.Scale(sin(2.*beta));
    1896         Center->AddVector(&helper);
    1897         helper.CopyVector(c);
    1898         helper.Scale(sin(2.*gamma));
    1899         Center->AddVector(&helper);
    1900         Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));
     1874  Vector helper;
     1875  double alpha, beta, gamma;
     1876  Vector SideA, SideB, SideC;
     1877  SideA.CopyVector(b);
     1878  SideA.SubtractVector(c);
     1879  SideB.CopyVector(c);
     1880  SideB.SubtractVector(a);
     1881  SideC.CopyVector(a);
     1882  SideC.SubtractVector(b);
     1883  alpha = M_PI - SideB.Angle(&SideC);
     1884  beta = M_PI - SideC.Angle(&SideA);
     1885  gamma = M_PI - SideA.Angle(&SideB);
     1886  cout << Verbose(3) << "INFO: alpha = " << alpha/M_PI*180. << ", beta = " << beta/M_PI*180. << ", gamma = " << gamma/M_PI*180. << "." << endl;
     1887  if (fabs(M_PI - alpha - beta - gamma) > HULLEPSILON)
     1888    cerr << "Sum of angles " << (alpha+beta+gamma)/M_PI*180. << " > 180 degrees by " << fabs(M_PI - alpha - beta - gamma)/M_PI*180. << "!" << endl;
     1889
     1890  Center->Zero();
     1891  helper.CopyVector(a);
     1892  helper.Scale(sin(2.*alpha));
     1893  Center->AddVector(&helper);
     1894  helper.CopyVector(b);
     1895  helper.Scale(sin(2.*beta));
     1896  Center->AddVector(&helper);
     1897  helper.CopyVector(c);
     1898  helper.Scale(sin(2.*gamma));
     1899  Center->AddVector(&helper);
     1900  Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));
    19011901};
    19021902
     
    19161916double GetPathLengthonCircumCircle(Vector &CircleCenter, Vector &CirclePlaneNormal, double CircleRadius, Vector &NewSphereCenter, Vector &OldSphereCenter, Vector &NormalVector, Vector &SearchDirection)
    19171917{
    1918         Vector helper;
    1919         double radius, alpha;
    1920 
    1921         helper.CopyVector(&NewSphereCenter);
    1922         // test whether new center is on the parameter circle's plane
    1923         if (fabs(helper.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
    1924                 cerr << "ERROR: Something's very wrong here: NewSphereCenter is not on the band's plane as desired by " <<fabs(helper.ScalarProduct(&CirclePlaneNormal))        << "!" << endl;
    1925                 helper.ProjectOntoPlane(&CirclePlaneNormal);
    1926         }
    1927         radius = helper.ScalarProduct(&helper);
    1928         // test whether the new center vector has length of CircleRadius
    1929         if (fabs(radius - CircleRadius) > HULLEPSILON)
    1930                 cerr << Verbose(1) << "ERROR: The projected center of the new sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
    1931         alpha = helper.Angle(&OldSphereCenter);
    1932         // make the angle unique by checking the halfplanes/search direction
    1933         if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)      // acos is not unique on [0, 2.*M_PI), hence extra check to decide between two half intervals
    1934                 alpha = 2.*M_PI - alpha;
    1935         cout << Verbose(2) << "INFO: RelativeNewSphereCenter is " << helper << ", RelativeOldSphereCenter is " << OldSphereCenter << " and resulting angle is " << alpha << "." << endl;
    1936         radius = helper.Distance(&OldSphereCenter);
    1937         helper.ProjectOntoPlane(&NormalVector);
    1938         // check whether new center is somewhat away or at least right over the current baseline to prevent intersecting triangles
    1939         if ((radius > HULLEPSILON) || (helper.Norm() < HULLEPSILON)) {
    1940                 cout << Verbose(2) << "INFO: Distance between old and new center is " << radius << " and between new center and baseline center is " << helper.Norm() << "." << endl;
    1941                 return alpha;
    1942         } else {
    1943                 cout << Verbose(1) << "ERROR: NewSphereCenter " << helper << " is too close to OldSphereCenter" << OldSphereCenter << "." << endl;
    1944                 return 2.*M_PI;
    1945         }
     1918  Vector helper;
     1919  double radius, alpha;
     1920
     1921  helper.CopyVector(&NewSphereCenter);
     1922  // test whether new center is on the parameter circle's plane
     1923  if (fabs(helper.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
     1924    cerr << "ERROR: Something's very wrong here: NewSphereCenter is not on the band's plane as desired by " <<fabs(helper.ScalarProduct(&CirclePlaneNormal))  << "!" << endl;
     1925    helper.ProjectOntoPlane(&CirclePlaneNormal);
     1926  }
     1927  radius = helper.ScalarProduct(&helper);
     1928  // test whether the new center vector has length of CircleRadius
     1929  if (fabs(radius - CircleRadius) > HULLEPSILON)
     1930    cerr << Verbose(1) << "ERROR: The projected center of the new sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
     1931  alpha = helper.Angle(&OldSphereCenter);
     1932  // make the angle unique by checking the halfplanes/search direction
     1933  if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)  // acos is not unique on [0, 2.*M_PI), hence extra check to decide between two half intervals
     1934    alpha = 2.*M_PI - alpha;
     1935  cout << Verbose(2) << "INFO: RelativeNewSphereCenter is " << helper << ", RelativeOldSphereCenter is " << OldSphereCenter << " and resulting angle is " << alpha << "." << endl;
     1936  radius = helper.Distance(&OldSphereCenter);
     1937  helper.ProjectOntoPlane(&NormalVector);
     1938  // check whether new center is somewhat away or at least right over the current baseline to prevent intersecting triangles
     1939  if ((radius > HULLEPSILON) || (helper.Norm() < HULLEPSILON)) {
     1940    cout << Verbose(2) << "INFO: Distance between old and new center is " << radius << " and between new center and baseline center is " << helper.Norm() << "." << endl;
     1941    return alpha;
     1942  } else {
     1943    cout << Verbose(1) << "ERROR: NewSphereCenter " << helper << " is too close to OldSphereCenter" << OldSphereCenter << "." << endl;
     1944    return 2.*M_PI;
     1945  }
    19461946};
    19471947
     
    19781978// void Find_next_suitable_point(class BoundaryTriangleSet *BaseTriangle, class BoundaryLineSet *BaseLine, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC)
    19791979// {
    1980 //      atom *Walker = NULL;
    1981 //       Vector CircleCenter;   // center of the circle, i.e. of the band of sphere's centers
    1982 //      Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in
    1983 //       Vector OldSphereCenter;        // center of the sphere defined by the three points of BaseTriangle
    1984 //       Vector NewSphereCenter;        // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility
    1985 //       Vector OtherNewSphereCenter;    // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility
    1986 //       Vector NewNormalVector;        // normal vector of the Candidate's triangle
    1987 //       Vector SearchDirection;        // vector that points out of BaseTriangle and is orthonormal to its NormalVector (i.e. the desired direction for the best Candidate)
    1988 //      Vector helper;
    1989 //      LinkedAtoms *List = NULL;
    1990 //      double CircleRadius; // radius of this circle
    1991 //      double radius;
    1992 //      double alpha, Otheralpha; // angles (i.e. parameter for the circle).
    1993 //      double Nullalpha; // angle between OldSphereCenter and NormalVector of base triangle
    1994 //      int N[NDIM], Nlower[NDIM], Nupper[NDIM];
    1995 //      atom *Candidate = NULL;
     1980//  atom *Walker = NULL;
     1981//   Vector CircleCenter;  // center of the circle, i.e. of the band of sphere's centers
     1982//  Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in
     1983//   Vector OldSphereCenter;  // center of the sphere defined by the three points of BaseTriangle
     1984//   Vector NewSphereCenter;  // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility
     1985//   Vector OtherNewSphereCenter;  // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility
     1986//   Vector NewNormalVector;  // normal vector of the Candidate's triangle
     1987//   Vector SearchDirection;  // vector that points out of BaseTriangle and is orthonormal to its NormalVector (i.e. the desired direction for the best Candidate)
     1988//  Vector helper;
     1989//  LinkedAtoms *List = NULL;
     1990//  double CircleRadius; // radius of this circle
     1991//  double radius;
     1992//  double alpha, Otheralpha; // angles (i.e. parameter for the circle).
     1993//  double Nullalpha; // angle between OldSphereCenter and NormalVector of base triangle
     1994//  int N[NDIM], Nlower[NDIM], Nupper[NDIM];
     1995//  atom *Candidate = NULL;
    19961996//
    1997 //      cout << Verbose(1) << "Begin of Find_next_suitable_point" << endl;
     1997//  cout << Verbose(1) << "Begin of Find_next_suitable_point" << endl;
    19981998//
    1999 //      cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << BaseTriangle->NormalVector << "." << endl;
     1999//  cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << BaseTriangle->NormalVector << "." << endl;
    20002000//
    2001 //      // construct center of circle
    2002 //      CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x));
    2003 //      CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x);
    2004 //      CircleCenter.Scale(0.5);
     2001//  // construct center of circle
     2002//  CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x));
     2003//  CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x);
     2004//  CircleCenter.Scale(0.5);
    20052005//
    2006 //      // construct normal vector of circle
    2007 //      CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x);
    2008 //      CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x);
     2006//  // construct normal vector of circle
     2007//  CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x);
     2008//  CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x);
    20092009//
    2010 //      // calculate squared radius of circle
    2011 //      radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
    2012 //      if (radius/4. < RADIUS*RADIUS) {
    2013 //              CircleRadius = RADIUS*RADIUS - radius/4.;
    2014 //              CirclePlaneNormal.Normalize();
    2015 //              cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
     2010//  // calculate squared radius of circle
     2011//  radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
     2012//  if (radius/4. < RADIUS*RADIUS) {
     2013//    CircleRadius = RADIUS*RADIUS - radius/4.;
     2014//    CirclePlaneNormal.Normalize();
     2015//    cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
    20162016//
    2017 //              // construct old center
    2018 //              GetCenterofCircumcircle(&OldSphereCenter, &(BaseTriangle->endpoints[0]->node->x), &(BaseTriangle->endpoints[1]->node->x), &(BaseTriangle->endpoints[2]->node->x));
    2019 //               helper.CopyVector(&BaseTriangle->NormalVector);        // normal vector ensures that this is correct center of the two possible ones
    2020 //              radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&OldSphereCenter);
    2021 //              helper.Scale(sqrt(RADIUS*RADIUS - radius));
    2022 //              OldSphereCenter.AddVector(&helper);
    2023 //              OldSphereCenter.SubtractVector(&CircleCenter);
    2024 //              cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;
     2017//    // construct old center
     2018//    GetCenterofCircumcircle(&OldSphereCenter, &(BaseTriangle->endpoints[0]->node->x), &(BaseTriangle->endpoints[1]->node->x), &(BaseTriangle->endpoints[2]->node->x));
     2019//     helper.CopyVector(&BaseTriangle->NormalVector);  // normal vector ensures that this is correct center of the two possible ones
     2020//    radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&OldSphereCenter);
     2021//    helper.Scale(sqrt(RADIUS*RADIUS - radius));
     2022//    OldSphereCenter.AddVector(&helper);
     2023//    OldSphereCenter.SubtractVector(&CircleCenter);
     2024//    cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;
    20252025//
    2026 //              // test whether old center is on the band's plane
    2027 //              if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
    2028 //                      cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl;
    2029 //                      OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal);
    2030 //              }
    2031 //              radius = OldSphereCenter.ScalarProduct(&OldSphereCenter);
    2032 //              if (fabs(radius - CircleRadius) < HULLEPSILON) {
     2026//    // test whether old center is on the band's plane
     2027//    if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
     2028//      cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl;
     2029//      OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal);
     2030//    }
     2031//    radius = OldSphereCenter.ScalarProduct(&OldSphereCenter);
     2032//    if (fabs(radius - CircleRadius) < HULLEPSILON) {
    20332033//
    2034 //                      // construct SearchDirection
    2035 //                      SearchDirection.MakeNormalVector(&BaseTriangle->NormalVector, &CirclePlaneNormal);
    2036 //                      helper.CopyVector(&BaseLine->endpoints[0]->node->x);
    2037 //                       for(int i=0;i<3;i++)   // just take next different endpoint
    2038 //                              if ((BaseTriangle->endpoints[i]->node != BaseLine->endpoints[0]->node) && (BaseTriangle->endpoints[i]->node != BaseLine->endpoints[1]->node)) {
    2039 //                                      helper.SubtractVector(&BaseTriangle->endpoints[i]->node->x);
    2040 //                              }
    2041 //                       if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)     // ohoh, SearchDirection points inwards!
    2042 //                              SearchDirection.Scale(-1.);
    2043 //                      SearchDirection.ProjectOntoPlane(&OldSphereCenter);
    2044 //                      SearchDirection.Normalize();
    2045 //                      cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
    2046 //                       if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {     // rotated the wrong way!
    2047 //                              cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl;
    2048 //                      }
     2034//      // construct SearchDirection
     2035//      SearchDirection.MakeNormalVector(&BaseTriangle->NormalVector, &CirclePlaneNormal);
     2036//      helper.CopyVector(&BaseLine->endpoints[0]->node->x);
     2037//       for(int i=0;i<3;i++)  // just take next different endpoint
     2038//        if ((BaseTriangle->endpoints[i]->node != BaseLine->endpoints[0]->node) && (BaseTriangle->endpoints[i]->node != BaseLine->endpoints[1]->node)) {
     2039//          helper.SubtractVector(&BaseTriangle->endpoints[i]->node->x);
     2040//        }
     2041//       if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)  // ohoh, SearchDirection points inwards!
     2042//        SearchDirection.Scale(-1.);
     2043//      SearchDirection.ProjectOntoPlane(&OldSphereCenter);
     2044//      SearchDirection.Normalize();
     2045//      cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
     2046//       if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {  // rotated the wrong way!
     2047//        cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl;
     2048//      }
    20492049//
    2050 //                       if (LC->SetIndexToVector(&CircleCenter)) {     // get cell for the starting atom
    2051 //                              for(int i=0;i<NDIM;i++) // store indices of this cell
    2052 //                                      N[i] = LC->n[i];
    2053 //                              cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
    2054 //                      } else {
    2055 //                              cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl;
    2056 //                              return;
    2057 //                      }
    2058 //                      // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
    2059 //                      cout << Verbose(2) << "LC Intervals:";
    2060 //                      for (int i=0;i<NDIM;i++) {
    2061 //                              Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
    2062 //                              Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
    2063 //                              cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
    2064 //                      }
    2065 //                      cout << endl;
    2066 //                      for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
    2067 //                              for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
    2068 //                                      for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
    2069 //                                              List = LC->GetCurrentCell();
    2070 //                                              cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
    2071 //                                              if (List != NULL) {
    2072 //                                                      for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
    2073 //                                                              Candidate = (*Runner);
     2050//       if (LC->SetIndexToVector(&CircleCenter)) {  // get cell for the starting atom
     2051//        for(int i=0;i<NDIM;i++) // store indices of this cell
     2052//          N[i] = LC->n[i];
     2053//        cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
     2054//      } else {
     2055//        cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl;
     2056//        return;
     2057//      }
     2058//      // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
     2059//      cout << Verbose(2) << "LC Intervals:";
     2060//      for (int i=0;i<NDIM;i++) {
     2061//        Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
     2062//        Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
     2063//        cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
     2064//      }
     2065//      cout << endl;
     2066//      for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
     2067//        for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
     2068//          for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
     2069//            List = LC->GetCurrentCell();
     2070//            cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
     2071//            if (List != NULL) {
     2072//              for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
     2073//                Candidate = (*Runner);
    20742074//
    2075 //                                                              // check for three unique points
    2076 //                                                              if ((Candidate != BaseTriangle->endpoints[0]->node) && (Candidate != BaseTriangle->endpoints[1]->node) && (Candidate != BaseTriangle->endpoints[2]->node)) {
    2077 //                                                                      cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl;
     2075//                // check for three unique points
     2076//                if ((Candidate != BaseTriangle->endpoints[0]->node) && (Candidate != BaseTriangle->endpoints[1]->node) && (Candidate != BaseTriangle->endpoints[2]->node)) {
     2077//                  cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl;
    20782078//
    2079 //                                                                      // construct both new centers
    2080 //                                                                      GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x));
    2081 //                                                                      OtherNewSphereCenter.CopyVector(&NewSphereCenter);
     2079//                  // construct both new centers
     2080//                  GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x));
     2081//                  OtherNewSphereCenter.CopyVector(&NewSphereCenter);
    20822082//
    2083 //                                                                      if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) {
    2084 //                                                                              helper.CopyVector(&NewNormalVector);
    2085 //                                                                              cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl;
    2086 //                                                                              radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter);
    2087 //                                                                              if (radius < RADIUS*RADIUS) {
    2088 //                                                                                      helper.Scale(sqrt(RADIUS*RADIUS - radius));
    2089 //                                                                                      cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl;
    2090 //                                                                                      NewSphereCenter.AddVector(&helper);
    2091 //                                                                                      NewSphereCenter.SubtractVector(&CircleCenter);
    2092 //                                                                                      cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl;
     2083//                  if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) {
     2084//                    helper.CopyVector(&NewNormalVector);
     2085//                    cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl;
     2086//                    radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter);
     2087//                    if (radius < RADIUS*RADIUS) {
     2088//                      helper.Scale(sqrt(RADIUS*RADIUS - radius));
     2089//                      cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl;
     2090//                      NewSphereCenter.AddVector(&helper);
     2091//                      NewSphereCenter.SubtractVector(&CircleCenter);
     2092//                      cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl;
    20932093//
    2094 //                                                                                      helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction
    2095 //                                                                                      OtherNewSphereCenter.AddVector(&helper);
    2096 //                                                                                      OtherNewSphereCenter.SubtractVector(&CircleCenter);
    2097 //                                                                                      cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl;
     2094//                      helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction
     2095//                      OtherNewSphereCenter.AddVector(&helper);
     2096//                      OtherNewSphereCenter.SubtractVector(&CircleCenter);
     2097//                      cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl;
    20982098//
    2099 //                                                                                      // check both possible centers
    2100 //                                                                                      alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection);
    2101 //                                                                                      Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection);
    2102 //                                                                                      alpha = min(alpha, Otheralpha);
    2103 //                                                                                      if (*ShortestAngle > alpha) {
    2104 //                                                                                                      OptCandidate = Candidate;
    2105 //                                                                                                      *ShortestAngle = alpha;
    2106 //                                                                                                      if (alpha != Otheralpha)
    2107 //                                                                                                              OptCandidateCenter->CopyVector(&NewSphereCenter);
    2108 //                                                                                                      else
    2109 //                                                                                                              OptCandidateCenter->CopyVector(&OtherNewSphereCenter);
    2110 //                                                                                                      cout << Verbose(1) << "We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl;
    2111 //                                                                                      } else {
    2112 //                                                                                              if (OptCandidate != NULL)
    2113 //                                                                                                      cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl;
    2114 //                                                                                              else
    2115 //                                                                                                      cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl;
    2116 //                                                                                      }
     2099//                      // check both possible centers
     2100//                      alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection);
     2101//                      Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection);
     2102//                      alpha = min(alpha, Otheralpha);
     2103//                      if (*ShortestAngle > alpha) {
     2104//                          OptCandidate = Candidate;
     2105//                          *ShortestAngle = alpha;
     2106//                          if (alpha != Otheralpha)
     2107//                            OptCandidateCenter->CopyVector(&NewSphereCenter);
     2108//                          else
     2109//                            OptCandidateCenter->CopyVector(&OtherNewSphereCenter);
     2110//                          cout << Verbose(1) << "We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl;
     2111//                      } else {
     2112//                        if (OptCandidate != NULL)
     2113//                          cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl;
     2114//                        else
     2115//                          cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl;
     2116//                      }
    21172117//
    2118 //                                                                              } else {
    2119 //                                                                                      cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl;
    2120 //                                                                              }
    2121 //                                                                      } else {
    2122 //                                                                              cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl;
    2123 //                                                                      }
    2124 //                                                              } else {
    2125 //                                                                      cout << Verbose(1) << "REJECT: Base triangle " << *BaseTriangle << " contains Candidate " << *Candidate << "." << endl;
    2126 //                                                              }
    2127 //                                                      }
    2128 //                                              }
    2129 //                                      }
    2130 //              } else {
    2131 //                      cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
    2132 //              }
    2133 //      } else {
    2134 //              cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and base triangle " << *BaseTriangle << " is too big!" << endl;
    2135 //      }
     2118//                    } else {
     2119//                      cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl;
     2120//                    }
     2121//                  } else {
     2122//                    cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl;
     2123//                  }
     2124//                } else {
     2125//                  cout << Verbose(1) << "REJECT: Base triangle " << *BaseTriangle << " contains Candidate " << *Candidate << "." << endl;
     2126//                }
     2127//              }
     2128//            }
     2129//          }
     2130//    } else {
     2131//      cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
     2132//    }
     2133//  } else {
     2134//    cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and base triangle " << *BaseTriangle << " is too big!" << endl;
     2135//  }
    21362136//
    2137 //      cout << Verbose(1) << "End of Find_next_suitable_point" << endl;
     2137//  cout << Verbose(1) << "End of Find_next_suitable_point" << endl;
    21382138// };
    21392139
     
    21482148 */
    21492149bool Tesselation::CheckPresenceOfTriangle(ofstream *out, atom *Candidates[3]) {
    2150         LineMap::iterator FindLine;
    2151         PointMap::iterator FindPoint;
    2152 
    2153         *out << Verbose(2) << "Begin of CheckPresenceOfTriangle" << endl;
    2154         for (int i=0;i<3;i++) { // check through all endpoints
    2155                 FindPoint = PointsOnBoundary.find(Candidates[i]->nr);
    2156                 if (FindPoint != PointsOnBoundary.end())
    2157                         TPS[i] = FindPoint->second;
    2158                 else
    2159                         TPS[i] = NULL;
    2160         }
    2161 
    2162         // check lines
    2163         for (int i=0;i<3;i++)
    2164                 if (TPS[i] != NULL)
    2165                         for (int j=i;j<3;j++)
    2166                                 if (TPS[j] != NULL) {
    2167                                         FindLine = TPS[i]->lines.find(TPS[j]->node->nr);
    2168                                         if ((FindLine != TPS[i]->lines.end()) && (FindLine->second->TrianglesCount > 1)) {
    2169                                                 *out << "WARNING: Line " << *FindLine->second << " already present with " << FindLine->second->TrianglesCount << " triangles attached." << endl;
    2170                                                 *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;
    2171                                                 return false;
    2172                                         }
    2173                                 }
    2174         *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;
    2175         return true;
     2150  LineMap::iterator FindLine;
     2151  PointMap::iterator FindPoint;
     2152
     2153  *out << Verbose(2) << "Begin of CheckPresenceOfTriangle" << endl;
     2154  for (int i=0;i<3;i++) { // check through all endpoints
     2155    FindPoint = PointsOnBoundary.find(Candidates[i]->nr);
     2156    if (FindPoint != PointsOnBoundary.end())
     2157      TPS[i] = FindPoint->second;
     2158    else
     2159      TPS[i] = NULL;
     2160  }
     2161
     2162  // check lines
     2163  for (int i=0;i<3;i++)
     2164    if (TPS[i] != NULL)
     2165      for (int j=i;j<3;j++)
     2166        if (TPS[j] != NULL) {
     2167          FindLine = TPS[i]->lines.find(TPS[j]->node->nr);
     2168          if ((FindLine != TPS[i]->lines.end()) && (FindLine->second->TrianglesCount > 1)) {
     2169            *out << "WARNING: Line " << *FindLine->second << " already present with " << FindLine->second->TrianglesCount << " triangles attached." << endl;
     2170            *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;
     2171            return false;
     2172          }
     2173        }
     2174  *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;
     2175  return true;
    21762176};
    21772177
     
    22112211void 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)
    22122212{
    2213         Vector CircleCenter;    // center of the circle, i.e. of the band of sphere's centers
    2214         Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in
    2215         Vector NewSphereCenter; // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility
    2216         Vector OtherNewSphereCenter;    // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility
    2217         Vector NewNormalVector; // normal vector of the Candidate's triangle
    2218         Vector helper;
    2219         LinkedAtoms *List = NULL;
    2220         double CircleRadius; // radius of this circle
    2221         double radius;
    2222         double alpha, Otheralpha; // angles (i.e. parameter for the circle).
    2223         int N[NDIM], Nlower[NDIM], Nupper[NDIM];
    2224         atom *Candidate = NULL;
    2225 
    2226         cout << Verbose(1) << "Begin of Find_third_point_for_Tesselation" << endl;
    2227 
    2228         cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl;
    2229 
    2230         // construct center of circle
    2231         CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x));
    2232         CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x);
    2233         CircleCenter.Scale(0.5);
    2234 
    2235         // construct normal vector of circle
    2236         CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x);
    2237         CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x);
    2238 
    2239         // calculate squared radius of circle
    2240         radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
    2241         if (radius/4. < RADIUS*RADIUS) {
    2242                 CircleRadius = RADIUS*RADIUS - radius/4.;
    2243                 CirclePlaneNormal.Normalize();
    2244                 cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
    2245 
    2246                 // test whether old center is on the band's plane
    2247                 if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
    2248                         cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl;
    2249                         OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal);
    2250                 }
    2251                 radius = OldSphereCenter.ScalarProduct(&OldSphereCenter);
    2252                 if (fabs(radius - CircleRadius) < HULLEPSILON) {
    2253 
    2254                         // check SearchDirection
    2255                         cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
    2256                         if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {      // rotated the wrong way!
    2257                                 cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are not orthogonal!" << endl;
    2258                         }
    2259                         // get cell for the starting atom
    2260                         if (LC->SetIndexToVector(&CircleCenter)) {
    2261                                         for(int i=0;i<NDIM;i++) // store indices of this cell
    2262                                         N[i] = LC->n[i];
    2263                                 cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
    2264                         } else {
    2265                                 cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl;
    2266                                 return;
    2267                         }
    2268                         // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
    2269                         cout << Verbose(2) << "LC Intervals:";
    2270                         for (int i=0;i<NDIM;i++) {
    2271                                 Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
    2272                                 Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
    2273                                 cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
    2274                         }
    2275                         cout << endl;
    2276                         for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
    2277                                 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
    2278                                         for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
    2279                                                 List = LC->GetCurrentCell();
    2280                                                 //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
    2281                                                 if (List != NULL) {
    2282                                                         for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
    2283                                                                 Candidate = (*Runner);
    2284 
    2285                                                                 // check for three unique points
    2286                                                                 if ((Candidate != BaseLine->endpoints[0]->node) && (Candidate != BaseLine->endpoints[1]->node) && (Candidate != ThirdNode)) {
    2287                                                                         cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl;
    2288 
    2289                                                                         // construct both new centers
    2290                                                                         GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x));
    2291                                                                         OtherNewSphereCenter.CopyVector(&NewSphereCenter);
    2292 
    2293                                                                         if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) {
    2294                                                                                 helper.CopyVector(&NewNormalVector);
    2295                                                                                 cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl;
    2296                                                                                 radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter);
    2297                                                                                 if (radius < RADIUS*RADIUS) {
    2298                                                                                         helper.Scale(sqrt(RADIUS*RADIUS - radius));
    2299                                                                                         cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl;
    2300                                                                                         NewSphereCenter.AddVector(&helper);
    2301                                                                                         NewSphereCenter.SubtractVector(&CircleCenter);
    2302                                                                                         cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl;
    2303 
    2304                                                                                         helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction
    2305                                                                                         OtherNewSphereCenter.AddVector(&helper);
    2306                                                                                         OtherNewSphereCenter.SubtractVector(&CircleCenter);
    2307                                                                                         cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl;
    2308 
    2309                                                                                         // check both possible centers
    2310                                                                                         alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, NormalVector, SearchDirection);
    2311                                                                                         Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, NormalVector, SearchDirection);
    2312                                                                                         alpha = min(alpha, Otheralpha);
    2313                                                                                         if (*ShortestAngle > alpha) {
    2314                                                                                                         OptCandidate = Candidate;
    2315                                                                                                         *ShortestAngle = alpha;
    2316                                                                                                         if (alpha != Otheralpha)
    2317                                                                                                                 OptCandidateCenter->CopyVector(&NewSphereCenter);
    2318                                                                                                         else
    2319                                                                                                                 OptCandidateCenter->CopyVector(&OtherNewSphereCenter);
    2320                                                                                                         cout << Verbose(1) << "ACCEPT: We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl;
    2321                                                                                         } else {
    2322                                                                                                 if (OptCandidate != NULL)
    2323                                                                                                         cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl;
    2324                                                                                                 else
    2325                                                                                                         cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl;
    2326                                                                                         }
    2327 
    2328                                                                                 } else {
    2329                                                                                         cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl;
    2330                                                                                 }
    2331                                                                         } else {
    2332                                                                                 cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl;
    2333                                                                         }
    2334                                                                 } else {
    2335                                                                         if (ThirdNode != NULL)
    2336                                                                                 cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " and " << *ThirdNode << " contains Candidate " << *Candidate << "." << endl;
    2337                                                                         else
    2338                                                                                 cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " contains Candidate " << *Candidate << "." << endl;
    2339                                                                 }
    2340                                                         }
    2341                                                 }
    2342                                         }
    2343                 } else {
    2344                         cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
    2345                 }
    2346         } else {
    2347                 if (ThirdNode != NULL)
    2348                         cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and third node " << *ThirdNode << " is too big!" << endl;
    2349                 else
    2350                         cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " is too big!" << endl;
    2351         }
    2352 
    2353         cout << Verbose(1) << "End of Find_third_point_for_Tesselation" << endl;
     2213  Vector CircleCenter;  // center of the circle, i.e. of the band of sphere's centers
     2214  Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in
     2215  Vector NewSphereCenter;  // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility
     2216  Vector OtherNewSphereCenter;  // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility
     2217  Vector NewNormalVector;  // normal vector of the Candidate's triangle
     2218  Vector helper;
     2219  LinkedAtoms *List = NULL;
     2220  double CircleRadius; // radius of this circle
     2221  double radius;
     2222  double alpha, Otheralpha; // angles (i.e. parameter for the circle).
     2223  int N[NDIM], Nlower[NDIM], Nupper[NDIM];
     2224  atom *Candidate = NULL;
     2225
     2226  cout << Verbose(1) << "Begin of Find_third_point_for_Tesselation" << endl;
     2227
     2228  cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl;
     2229
     2230  // construct center of circle
     2231  CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x));
     2232  CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x);
     2233  CircleCenter.Scale(0.5);
     2234
     2235  // construct normal vector of circle
     2236  CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x);
     2237  CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x);
     2238
     2239  // calculate squared radius of circle
     2240  radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
     2241  if (radius/4. < RADIUS*RADIUS) {
     2242    CircleRadius = RADIUS*RADIUS - radius/4.;
     2243    CirclePlaneNormal.Normalize();
     2244    cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
     2245
     2246    // test whether old center is on the band's plane
     2247    if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
     2248      cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl;
     2249      OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal);
     2250    }
     2251    radius = OldSphereCenter.ScalarProduct(&OldSphereCenter);
     2252    if (fabs(radius - CircleRadius) < HULLEPSILON) {
     2253
     2254      // check SearchDirection
     2255      cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
     2256      if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {  // rotated the wrong way!
     2257        cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are not orthogonal!" << endl;
     2258      }
     2259      // get cell for the starting atom
     2260      if (LC->SetIndexToVector(&CircleCenter)) {
     2261          for(int i=0;i<NDIM;i++) // store indices of this cell
     2262          N[i] = LC->n[i];
     2263        cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
     2264      } else {
     2265        cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl;
     2266        return;
     2267      }
     2268      // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
     2269      cout << Verbose(2) << "LC Intervals:";
     2270      for (int i=0;i<NDIM;i++) {
     2271        Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
     2272        Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
     2273        cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
     2274      }
     2275      cout << endl;
     2276      for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
     2277        for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
     2278          for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
     2279            List = LC->GetCurrentCell();
     2280            //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
     2281            if (List != NULL) {
     2282              for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
     2283                Candidate = (*Runner);
     2284
     2285                // check for three unique points
     2286                if ((Candidate != BaseLine->endpoints[0]->node) && (Candidate != BaseLine->endpoints[1]->node) && (Candidate != ThirdNode)) {
     2287                  cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl;
     2288
     2289                  // construct both new centers
     2290                  GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x));
     2291                  OtherNewSphereCenter.CopyVector(&NewSphereCenter);
     2292
     2293                  if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) {
     2294                    helper.CopyVector(&NewNormalVector);
     2295                    cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl;
     2296                    radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter);
     2297                    if (radius < RADIUS*RADIUS) {
     2298                      helper.Scale(sqrt(RADIUS*RADIUS - radius));
     2299                      cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl;
     2300                      NewSphereCenter.AddVector(&helper);
     2301                      NewSphereCenter.SubtractVector(&CircleCenter);
     2302                      cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl;
     2303
     2304                      helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction
     2305                      OtherNewSphereCenter.AddVector(&helper);
     2306                      OtherNewSphereCenter.SubtractVector(&CircleCenter);
     2307                      cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl;
     2308
     2309                      // check both possible centers
     2310                      alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, NormalVector, SearchDirection);
     2311                      Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, NormalVector, SearchDirection);
     2312                      alpha = min(alpha, Otheralpha);
     2313                      if (*ShortestAngle > alpha) {
     2314                          OptCandidate = Candidate;
     2315                          *ShortestAngle = alpha;
     2316                          if (alpha != Otheralpha)
     2317                            OptCandidateCenter->CopyVector(&NewSphereCenter);
     2318                          else
     2319                            OptCandidateCenter->CopyVector(&OtherNewSphereCenter);
     2320                          cout << Verbose(1) << "ACCEPT: We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl;
     2321                      } else {
     2322                        if (OptCandidate != NULL)
     2323                          cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl;
     2324                        else
     2325                          cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl;
     2326                      }
     2327
     2328                    } else {
     2329                      cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl;
     2330                    }
     2331                  } else {
     2332                    cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl;
     2333                  }
     2334                } else {
     2335                  if (ThirdNode != NULL)
     2336                    cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " and " << *ThirdNode << " contains Candidate " << *Candidate << "." << endl;
     2337                  else
     2338                    cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " contains Candidate " << *Candidate << "." << endl;
     2339                }
     2340              }
     2341            }
     2342          }
     2343    } else {
     2344      cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
     2345    }
     2346  } else {
     2347    if (ThirdNode != NULL)
     2348      cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and third node " << *ThirdNode << " is too big!" << endl;
     2349    else
     2350      cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " is too big!" << endl;
     2351  }
     2352
     2353  cout << Verbose(1) << "End of Find_third_point_for_Tesselation" << endl;
    23542354};
    23552355
     
    23652365void Find_second_point_for_Tesselation(atom* a, atom* Candidate, Vector Oben, atom*& Opt_Candidate, double Storage[3], double RADIUS, LinkedCell *LC)
    23662366{
    2367         cout << Verbose(2) << "Begin of Find_second_point_for_Tesselation" << endl;
    2368         Vector AngleCheck;
    2369         double norm = -1., angle;
    2370         LinkedAtoms *List = NULL;
    2371         int N[NDIM], Nlower[NDIM], Nupper[NDIM];
    2372 
    2373         if (LC->SetIndexToAtom(a)) {    // get cell for the starting atom
    2374                 for(int i=0;i<NDIM;i++) // store indices of this cell
    2375                         N[i] = LC->n[i];
    2376         } else {
    2377                 cerr << "ERROR: Atom " << *a << " is not found in cell " << LC->index << "." << endl;
    2378                 return;
    2379         }
    2380         // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
    2381         cout << Verbose(2) << "LC Intervals:";
    2382         for (int i=0;i<NDIM;i++) {
    2383                 Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
    2384                 Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
    2385                 cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
    2386         }
    2387         cout << endl;
    2388         for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
    2389                 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
    2390                         for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
    2391                                 List = LC->GetCurrentCell();
    2392                                 //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
    2393                                 if (List != NULL) {
    2394                                         for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
    2395                                                 Candidate = (*Runner);
    2396                                                                 // check if we only have one unique point yet ...
    2397                                                                 if (a != Candidate) {
    2398                         cout << Verbose(3) << "Current candidate is " << *Candidate << ": ";
    2399                         AngleCheck.CopyVector(&(Candidate->x));
    2400                         AngleCheck.SubtractVector(&(a->x));
    2401                         norm = AngleCheck.Norm();
    2402                                                         // second point shall have smallest angle with respect to Oben vector
    2403                                                         if (norm < RADIUS) {
    2404                                                                 angle = AngleCheck.Angle(&Oben);
    2405                                                                 if (angle < Storage[0]) {
    2406                                                                         //cout << Verbose(1) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[1]);
    2407                                                                         cout << "Is a better candidate with distance " << norm << " and " << angle << ".\n";
    2408                                                                         Opt_Candidate = Candidate;
    2409                                                                         Storage[0] = AngleCheck.Angle(&Oben);
    2410                                                                         //cout << Verbose(1) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[2]);
    2411                                                                 } else {
    2412                                                                         cout << "Looses with angle " << angle << " to a better candidate " << *Opt_Candidate << endl;
    2413                                                                 }
    2414                                                         } else {
    2415                                                                 cout << "Refused due to Radius " << norm << endl;
    2416                                                         }
    2417                                                 }
    2418                                         }
    2419                                 }
    2420                         }
    2421         cout << Verbose(2) << "End of Find_second_point_for_Tesselation" << endl;
     2367  cout << Verbose(2) << "Begin of Find_second_point_for_Tesselation" << endl;
     2368  Vector AngleCheck;
     2369  double norm = -1., angle;
     2370  LinkedAtoms *List = NULL;
     2371  int N[NDIM], Nlower[NDIM], Nupper[NDIM];
     2372
     2373  if (LC->SetIndexToAtom(a)) {  // get cell for the starting atom
     2374    for(int i=0;i<NDIM;i++) // store indices of this cell
     2375      N[i] = LC->n[i];
     2376  } else {
     2377    cerr << "ERROR: Atom " << *a << " is not found in cell " << LC->index << "." << endl;
     2378    return;
     2379  }
     2380  // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
     2381  cout << Verbose(2) << "LC Intervals:";
     2382  for (int i=0;i<NDIM;i++) {
     2383    Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
     2384    Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
     2385    cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
     2386  }
     2387  cout << endl;
     2388  for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
     2389    for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
     2390      for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
     2391        List = LC->GetCurrentCell();
     2392        //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
     2393        if (List != NULL) {
     2394          for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
     2395            Candidate = (*Runner);
     2396                // check if we only have one unique point yet ...
     2397                if (a != Candidate) {
     2398      cout << Verbose(3) << "Current candidate is " << *Candidate << ": ";
     2399      AngleCheck.CopyVector(&(Candidate->x));
     2400      AngleCheck.SubtractVector(&(a->x));
     2401      norm = AngleCheck.Norm();
     2402              // second point shall have smallest angle with respect to Oben vector
     2403              if (norm < RADIUS) {
     2404                angle = AngleCheck.Angle(&Oben);
     2405                if (angle < Storage[0]) {
     2406                  //cout << Verbose(1) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[1]);
     2407                  cout << "Is a better candidate with distance " << norm << " and " << angle << ".\n";
     2408                  Opt_Candidate = Candidate;
     2409                  Storage[0] = AngleCheck.Angle(&Oben);
     2410                  //cout << Verbose(1) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[2]);
     2411                } else {
     2412                  cout << "Looses with angle " << angle << " to a better candidate " << *Opt_Candidate << endl;
     2413                }
     2414              } else {
     2415                cout << "Refused due to Radius " << norm << endl;
     2416              }
     2417            }
     2418          }
     2419        }
     2420      }
     2421  cout << Verbose(2) << "End of Find_second_point_for_Tesselation" << endl;
    24222422};
    24232423
     
    24312431void Tesselation::Find_starting_triangle(ofstream *out, molecule *mol, const double RADIUS, LinkedCell *LC)
    24322432{
    2433         cout << Verbose(1) << "Begin of Find_starting_triangle\n";
    2434         int i = 0;
    2435         LinkedAtoms *List = NULL;
    2436         atom* FirstPoint;
    2437         atom* SecondPoint;
    2438         atom* MaxAtom[NDIM];
    2439         double max_coordinate[NDIM];
    2440         Vector Oben;
    2441         Vector helper;
    2442         Vector Chord;
    2443         Vector SearchDirection;
    2444         Vector OptCandidateCenter;
    2445 
    2446         Oben.Zero();
    2447 
    2448         for (i = 0; i < 3; i++) {
    2449                 MaxAtom[i] = NULL;
    2450                 max_coordinate[i] = -1;
    2451         }
    2452 
    2453         // 1. searching topmost atom with respect to each axis
    2454         for (int i=0;i<NDIM;i++) { // each axis
    2455                 LC->n[i] = LC->N[i]-1; // current axis is topmost cell
    2456                 for (LC->n[(i+1)%NDIM]=0;LC->n[(i+1)%NDIM]<LC->N[(i+1)%NDIM];LC->n[(i+1)%NDIM]++)
    2457                         for (LC->n[(i+2)%NDIM]=0;LC->n[(i+2)%NDIM]<LC->N[(i+2)%NDIM];LC->n[(i+2)%NDIM]++) {
    2458                                 List = LC->GetCurrentCell();
    2459                                 //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
    2460                                 if (List != NULL) {
    2461                                         for (LinkedAtoms::iterator Runner = List->begin();Runner != List->end();Runner++) {
    2462                                                 cout << Verbose(2) << "Current atom is " << *(*Runner) << "." << endl;
    2463                                                 if ((*Runner)->x.x[i] > max_coordinate[i]) {
    2464                                                         max_coordinate[i] = (*Runner)->x.x[i];
    2465                                                         MaxAtom[i] = (*Runner);
    2466                                                 }
    2467                                         }
    2468                                 } else {
    2469                                         cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << " is invalid!" << endl;
    2470                                 }
    2471                         }
    2472         }
    2473 
    2474         cout << Verbose(2) << "Found maximum coordinates: ";
    2475         for (int i=0;i<NDIM;i++)
    2476                 cout << i << ": " << *MaxAtom[i] << "\t";
    2477         cout << endl;
    2478         const int k = 1;                // arbitrary choice
    2479         Oben.x[k] = 1.;
    2480         FirstPoint = MaxAtom[k];
    2481         cout << Verbose(1) << "Coordinates of start atom " << *FirstPoint << " at " << FirstPoint->x << "." << endl;
    2482 
    2483         // add first point
    2484         AddTrianglePoint(FirstPoint, 0);
    2485 
    2486         double ShortestAngle;
    2487         atom* Opt_Candidate = NULL;
    2488         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.
    2489 
    2490         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_...
    2491         SecondPoint = Opt_Candidate;
    2492         cout << Verbose(1) << "Found second point is " << *SecondPoint << " at " << SecondPoint->x << ".\n";
    2493 
    2494         // add second point and first baseline
    2495         AddTrianglePoint(SecondPoint, 1);
    2496         AddTriangleLine(TPS[0], TPS[1], 0);
    2497 
    2498         helper.CopyVector(&(FirstPoint->x));
    2499         helper.SubtractVector(&(SecondPoint->x));
    2500         helper.Normalize();
    2501         Oben.ProjectOntoPlane(&helper);
    2502         Oben.Normalize();
    2503         helper.VectorProduct(&Oben);
    2504         ShortestAngle = 2.*M_PI; // This will indicate the quadrant.
    2505 
    2506         Chord.CopyVector(&(FirstPoint->x)); // bring into calling function
    2507         Chord.SubtractVector(&(SecondPoint->x));
    2508         double radius = Chord.ScalarProduct(&Chord);
    2509         double CircleRadius = sqrt(RADIUS*RADIUS - radius/4.);
    2510         helper.CopyVector(&Oben);
    2511         helper.Scale(CircleRadius);
    2512         // Now, oben and helper are two orthonormalized vectors in the plane defined by Chord (not normalized)
    2513 
    2514         cout << Verbose(2) << "Looking for third point candidates \n";
    2515         // look in one direction of baseline for initial candidate
    2516         Opt_Candidate = NULL;
    2517         SearchDirection.MakeNormalVector(&Chord, &Oben);        // whether we look "left" first or "right" first is not important ...
    2518 
    2519         cout << Verbose(1) << "Looking for third point candidates ...\n";
    2520         Find_third_point_for_Tesselation(Oben, SearchDirection, helper, BLS[0], NULL, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC);
    2521         cout << Verbose(1) << "Third Point is " << *Opt_Candidate << endl;
    2522 
    2523         // add third point
    2524         AddTrianglePoint(Opt_Candidate, 2);
    2525 
    2526         // FOUND Starting Triangle: FirstPoint, SecondPoint, Opt_Candidate
    2527 
    2528         // Finally, we only have to add the found further lines
    2529         AddTriangleLine(TPS[1], TPS[2], 1);
    2530         AddTriangleLine(TPS[0], TPS[2], 2);
    2531         // ... and triangles to the Maps of the Tesselation class
    2532         BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    2533         AddTriangleToLines();
    2534         // ... and calculate its normal vector (with correct orientation)
    2535         OptCandidateCenter.Scale(-1.);
    2536         cout << Verbose(2) << "Oben is currently " << OptCandidateCenter << "." << endl;
    2537         BTS->GetNormalVector(OptCandidateCenter);
    2538         cout << Verbose(0) << "==> The found starting triangle consists of " << *FirstPoint << ", " << *SecondPoint << " and " << *Opt_Candidate << " with normal vector " << BTS->NormalVector << ".\n";
    2539         cout << Verbose(2) << "Projection is " << BTS->NormalVector.Projection(&Oben) << "." << endl;
    2540         cout << Verbose(1) << "End of Find_starting_triangle\n";
     2433  cout << Verbose(1) << "Begin of Find_starting_triangle\n";
     2434  int i = 0;
     2435  LinkedAtoms *List = NULL;
     2436  atom* FirstPoint;
     2437  atom* SecondPoint;
     2438  atom* MaxAtom[NDIM];
     2439  double max_coordinate[NDIM];
     2440  Vector Oben;
     2441  Vector helper;
     2442  Vector Chord;
     2443  Vector SearchDirection;
     2444  Vector OptCandidateCenter;
     2445
     2446  Oben.Zero();
     2447
     2448  for (i = 0; i < 3; i++) {
     2449    MaxAtom[i] = NULL;
     2450    max_coordinate[i] = -1;
     2451  }
     2452
     2453  // 1. searching topmost atom with respect to each axis
     2454  for (int i=0;i<NDIM;i++) { // each axis
     2455    LC->n[i] = LC->N[i]-1; // current axis is topmost cell
     2456    for (LC->n[(i+1)%NDIM]=0;LC->n[(i+1)%NDIM]<LC->N[(i+1)%NDIM];LC->n[(i+1)%NDIM]++)
     2457      for (LC->n[(i+2)%NDIM]=0;LC->n[(i+2)%NDIM]<LC->N[(i+2)%NDIM];LC->n[(i+2)%NDIM]++) {
     2458        List = LC->GetCurrentCell();
     2459        //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
     2460        if (List != NULL) {
     2461          for (LinkedAtoms::iterator Runner = List->begin();Runner != List->end();Runner++) {
     2462            cout << Verbose(2) << "Current atom is " << *(*Runner) << "." << endl;
     2463            if ((*Runner)->x.x[i] > max_coordinate[i]) {
     2464              max_coordinate[i] = (*Runner)->x.x[i];
     2465              MaxAtom[i] = (*Runner);
     2466            }
     2467          }
     2468        } else {
     2469          cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << " is invalid!" << endl;
     2470        }
     2471      }
     2472  }
     2473
     2474  cout << Verbose(2) << "Found maximum coordinates: ";
     2475  for (int i=0;i<NDIM;i++)
     2476    cout << i << ": " << *MaxAtom[i] << "\t";
     2477  cout << endl;
     2478  const int k = 1;    // arbitrary choice
     2479  Oben.x[k] = 1.;
     2480  FirstPoint = MaxAtom[k];
     2481  cout << Verbose(1) << "Coordinates of start atom " << *FirstPoint << " at " << FirstPoint->x << "." << endl;
     2482
     2483  // add first point
     2484  AddTrianglePoint(FirstPoint, 0);
     2485
     2486  double ShortestAngle;
     2487  atom* Opt_Candidate = NULL;
     2488  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.
     2489
     2490  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_...
     2491  SecondPoint = Opt_Candidate;
     2492  cout << Verbose(1) << "Found second point is " << *SecondPoint << " at " << SecondPoint->x << ".\n";
     2493
     2494  // add second point and first baseline
     2495  AddTrianglePoint(SecondPoint, 1);
     2496  AddTriangleLine(TPS[0], TPS[1], 0);
     2497
     2498  helper.CopyVector(&(FirstPoint->x));
     2499  helper.SubtractVector(&(SecondPoint->x));
     2500  helper.Normalize();
     2501  Oben.ProjectOntoPlane(&helper);
     2502  Oben.Normalize();
     2503  helper.VectorProduct(&Oben);
     2504  ShortestAngle = 2.*M_PI; // This will indicate the quadrant.
     2505
     2506  Chord.CopyVector(&(FirstPoint->x)); // bring into calling function
     2507  Chord.SubtractVector(&(SecondPoint->x));
     2508  double radius = Chord.ScalarProduct(&Chord);
     2509  double CircleRadius = sqrt(RADIUS*RADIUS - radius/4.);
     2510  helper.CopyVector(&Oben);
     2511  helper.Scale(CircleRadius);
     2512  // Now, oben and helper are two orthonormalized vectors in the plane defined by Chord (not normalized)
     2513
     2514  cout << Verbose(2) << "Looking for third point candidates \n";
     2515  // look in one direction of baseline for initial candidate
     2516  Opt_Candidate = NULL;
     2517  SearchDirection.MakeNormalVector(&Chord, &Oben);  // whether we look "left" first or "right" first is not important ...
     2518
     2519  cout << Verbose(1) << "Looking for third point candidates ...\n";
     2520  Find_third_point_for_Tesselation(Oben, SearchDirection, helper, BLS[0], NULL, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC);
     2521  cout << Verbose(1) << "Third Point is " << *Opt_Candidate << endl;
     2522
     2523  // add third point
     2524  AddTrianglePoint(Opt_Candidate, 2);
     2525
     2526  // FOUND Starting Triangle: FirstPoint, SecondPoint, Opt_Candidate
     2527
     2528  // Finally, we only have to add the found further lines
     2529  AddTriangleLine(TPS[1], TPS[2], 1);
     2530  AddTriangleLine(TPS[0], TPS[2], 2);
     2531  // ... and triangles to the Maps of the Tesselation class
     2532  BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     2533  AddTriangleToLines();
     2534  // ... and calculate its normal vector (with correct orientation)
     2535  OptCandidateCenter.Scale(-1.);
     2536  cout << Verbose(2) << "Oben is currently " << OptCandidateCenter << "." << endl;
     2537  BTS->GetNormalVector(OptCandidateCenter);
     2538  cout << Verbose(0) << "==> The found starting triangle consists of " << *FirstPoint << ", " << *SecondPoint << " and " << *Opt_Candidate << " with normal vector " << BTS->NormalVector << ".\n";
     2539  cout << Verbose(2) << "Projection is " << BTS->NormalVector.Projection(&Oben) << "." << endl;
     2540  cout << Verbose(1) << "End of Find_starting_triangle\n";
    25412541};
    25422542
     
    25522552 */
    25532553bool Tesselation::Find_next_suitable_triangle(ofstream *out,
    2554                 molecule *mol, BoundaryLineSet &Line, BoundaryTriangleSet &T,
    2555                 const double& RADIUS, int N, const char *tempbasename, LinkedCell *LC)
    2556 {
    2557         cout << Verbose(1) << "Begin of Find_next_suitable_triangle\n";
    2558         ofstream *tempstream = NULL;
    2559         char NumberName[255];
    2560 
    2561         atom* Opt_Candidate = NULL;
    2562         Vector OptCandidateCenter;
    2563 
    2564         Vector CircleCenter;
    2565         Vector CirclePlaneNormal;
    2566         Vector OldSphereCenter;
    2567         Vector SearchDirection;
    2568         Vector helper;
    2569         atom *ThirdNode = NULL;
    2570         double ShortestAngle = 2.*M_PI; // This will indicate the quadrant.
    2571         double radius, CircleRadius;
    2572 
    2573         cout << Verbose(1) << "Current baseline is " << Line << " of triangle " << T << "." << endl;
    2574         for (int i=0;i<3;i++)
    2575                 if ((T.endpoints[i]->node != Line.endpoints[0]->node) && (T.endpoints[i]->node != Line.endpoints[1]->node))
    2576                         ThirdNode = T.endpoints[i]->node;
    2577 
    2578         // construct center of circle
    2579         CircleCenter.CopyVector(&Line.endpoints[0]->node->x);
    2580         CircleCenter.AddVector(&Line.endpoints[1]->node->x);
    2581         CircleCenter.Scale(0.5);
    2582 
    2583         // construct normal vector of circle
    2584         CirclePlaneNormal.CopyVector(&Line.endpoints[0]->node->x);
    2585         CirclePlaneNormal.SubtractVector(&Line.endpoints[1]->node->x);
    2586 
    2587         // calculate squared radius of circle
    2588         radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
    2589         if (radius/4. < RADIUS*RADIUS) {
    2590                 CircleRadius = RADIUS*RADIUS - radius/4.;
    2591                 CirclePlaneNormal.Normalize();
    2592                 cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
    2593 
    2594                 // construct old center
    2595                 GetCenterofCircumcircle(&OldSphereCenter, &(T.endpoints[0]->node->x), &(T.endpoints[1]->node->x), &(T.endpoints[2]->node->x));
    2596                 helper.CopyVector(&T.NormalVector);     // normal vector ensures that this is correct center of the two possible ones
    2597                 radius = Line.endpoints[0]->node->x.DistanceSquared(&OldSphereCenter);
    2598                 helper.Scale(sqrt(RADIUS*RADIUS - radius));
    2599                 OldSphereCenter.AddVector(&helper);
    2600                 OldSphereCenter.SubtractVector(&CircleCenter);
    2601                 cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;
    2602 
    2603                 // construct SearchDirection
    2604                 SearchDirection.MakeNormalVector(&T.NormalVector, &CirclePlaneNormal);
    2605                 helper.CopyVector(&Line.endpoints[0]->node->x);
    2606                 helper.SubtractVector(&ThirdNode->x);
    2607                 if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)      // ohoh, SearchDirection points inwards!
    2608                         SearchDirection.Scale(-1.);
    2609                 SearchDirection.ProjectOntoPlane(&OldSphereCenter);
    2610                 SearchDirection.Normalize();
    2611                 cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
    2612                 if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {      // rotated the wrong way!
    2613                         cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl;
    2614                 }
    2615 
    2616                 // add third point
    2617                 cout << Verbose(1) << "Looking for third point candidates for triangle ... " << endl;
    2618                 Find_third_point_for_Tesselation(T.NormalVector, SearchDirection, OldSphereCenter, &Line, ThirdNode, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC);
    2619 
    2620         } else {
    2621                 cout << Verbose(1) << "Circumcircle for base line " << Line << " and base triangle " << T << " is too big!" << endl;
    2622         }
    2623 
    2624         if (Opt_Candidate == NULL) {
    2625                 cerr << "WARNING: Could not find a suitable candidate." << endl;
    2626                 return false;
    2627         }
    2628         cout << Verbose(1) << " Optimal candidate is " << *Opt_Candidate << " with circumsphere's center at " << OptCandidateCenter << "." << endl;
    2629 
    2630         // check whether all edges of the new triangle still have space for one more triangle (i.e. TriangleCount <2)
    2631         atom *AtomCandidates[3];
    2632         AtomCandidates[0] = Opt_Candidate;
    2633         AtomCandidates[1] = Line.endpoints[0]->node;
    2634         AtomCandidates[2] = Line.endpoints[1]->node;
    2635         bool flag = CheckPresenceOfTriangle(out, AtomCandidates);
    2636 
    2637         if (flag) { // if so, add
    2638                 AddTrianglePoint(Opt_Candidate, 0);
    2639                 AddTrianglePoint(Line.endpoints[0]->node, 1);
    2640                 AddTrianglePoint(Line.endpoints[1]->node, 2);
    2641 
    2642                 AddTriangleLine(TPS[0], TPS[1], 0);
    2643                 AddTriangleLine(TPS[0], TPS[2], 1);
    2644                 AddTriangleLine(TPS[1], TPS[2], 2);
    2645 
    2646                 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    2647                 AddTriangleToLines();
    2648 
    2649                 OptCandidateCenter.Scale(-1.);
    2650                 BTS->GetNormalVector(OptCandidateCenter);
    2651                 OptCandidateCenter.Scale(-1.);
    2652 
    2653                 cout << "--> New triangle with " << *BTS << " and normal vector " << BTS->NormalVector << " for this triangle ... " << endl;
    2654                 cout << Verbose(1) << "We have "<< TrianglesOnBoundaryCount << " for line " << Line << "." << endl;
    2655         } else { // else, yell and do nothing
    2656                 cout << Verbose(1) << "This triangle consisting of ";
    2657                 cout << *Opt_Candidate << ", ";
    2658                 cout << *Line.endpoints[0]->node << " and ";
    2659                 cout << *Line.endpoints[1]->node << " ";
    2660                 cout << "is invalid!" << endl;
    2661                 return false;
    2662         }
    2663 
    2664         if (flag && (DoSingleStepOutput && (TrianglesOnBoundaryCount % 10 == 0))) { // if we have a new triangle and want to output each new triangle configuration
    2665                 sprintf(NumberName, "-%04d-%s_%s_%s", TriangleFilesWritten, BTS->endpoints[0]->node->Name, BTS->endpoints[1]->node->Name, BTS->endpoints[2]->node->Name);
    2666                 if (DoTecplotOutput) {
    2667                         string NameofTempFile(tempbasename);
    2668                         NameofTempFile.append(NumberName);
    2669                         for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
    2670                                 NameofTempFile.erase(npos, 1);
    2671                         NameofTempFile.append(TecplotSuffix);
    2672                         cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
    2673                         tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
    2674                         write_tecplot_file(out, tempstream, this, mol, TriangleFilesWritten);
    2675                         tempstream->close();
    2676                         tempstream->flush();
    2677                         delete(tempstream);
    2678                 }
    2679 
    2680                 if (DoRaster3DOutput) {
    2681                         string NameofTempFile(tempbasename);
    2682                         NameofTempFile.append(NumberName);
    2683                         for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
    2684                                 NameofTempFile.erase(npos, 1);
    2685                         NameofTempFile.append(Raster3DSuffix);
    2686                         cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
    2687                         tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
    2688                         write_raster3d_file(out, tempstream, this, mol);
    2689                         // include the current position of the virtual sphere in the temporary raster3d file
    2690                         // make the circumsphere's center absolute again
    2691                         helper.CopyVector(&Line.endpoints[0]->node->x);
    2692                         helper.AddVector(&Line.endpoints[1]->node->x);
    2693                         helper.Scale(0.5);
    2694                         OptCandidateCenter.AddVector(&helper);
    2695                         Vector *center = mol->DetermineCenterOfAll(out);
    2696                         OptCandidateCenter.AddVector(center);
    2697                         delete(center);
    2698                         // and add to file plus translucency object
    2699                         *tempstream << "# current virtual sphere\n";
    2700                         *tempstream << "8\n     25.0            0.6              -1.0 -1.0 -1.0          0.2                            0 0 0 0\n";
    2701                         *tempstream << "2\n     " << OptCandidateCenter.x[0] << " " << OptCandidateCenter.x[1] << " " << OptCandidateCenter.x[2] << "\t" << RADIUS << "\t1 0 0\n";
    2702                         *tempstream << "9\n     terminating special property\n";
    2703                         tempstream->close();
    2704                         tempstream->flush();
    2705                         delete(tempstream);
    2706                 }
    2707                 if (DoTecplotOutput || DoRaster3DOutput)
    2708                         TriangleFilesWritten++;
    2709         }
    2710 
    2711         cout << Verbose(1) << "End of Find_next_suitable_triangle\n";
    2712         return true;
     2554    molecule *mol, BoundaryLineSet &Line, BoundaryTriangleSet &T,
     2555    const double& RADIUS, int N, const char *tempbasename, LinkedCell *LC)
     2556{
     2557  cout << Verbose(1) << "Begin of Find_next_suitable_triangle\n";
     2558  ofstream *tempstream = NULL;
     2559  char NumberName[255];
     2560
     2561  atom* Opt_Candidate = NULL;
     2562  Vector OptCandidateCenter;
     2563
     2564  Vector CircleCenter;
     2565  Vector CirclePlaneNormal;
     2566  Vector OldSphereCenter;
     2567  Vector SearchDirection;
     2568  Vector helper;
     2569  atom *ThirdNode = NULL;
     2570  double ShortestAngle = 2.*M_PI; // This will indicate the quadrant.
     2571  double radius, CircleRadius;
     2572
     2573  cout << Verbose(1) << "Current baseline is " << Line << " of triangle " << T << "." << endl;
     2574  for (int i=0;i<3;i++)
     2575    if ((T.endpoints[i]->node != Line.endpoints[0]->node) && (T.endpoints[i]->node != Line.endpoints[1]->node))
     2576      ThirdNode = T.endpoints[i]->node;
     2577
     2578  // construct center of circle
     2579  CircleCenter.CopyVector(&Line.endpoints[0]->node->x);
     2580  CircleCenter.AddVector(&Line.endpoints[1]->node->x);
     2581  CircleCenter.Scale(0.5);
     2582
     2583  // construct normal vector of circle
     2584  CirclePlaneNormal.CopyVector(&Line.endpoints[0]->node->x);
     2585  CirclePlaneNormal.SubtractVector(&Line.endpoints[1]->node->x);
     2586
     2587  // calculate squared radius of circle
     2588  radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
     2589  if (radius/4. < RADIUS*RADIUS) {
     2590    CircleRadius = RADIUS*RADIUS - radius/4.;
     2591    CirclePlaneNormal.Normalize();
     2592    cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
     2593
     2594    // construct old center
     2595    GetCenterofCircumcircle(&OldSphereCenter, &(T.endpoints[0]->node->x), &(T.endpoints[1]->node->x), &(T.endpoints[2]->node->x));
     2596    helper.CopyVector(&T.NormalVector);  // normal vector ensures that this is correct center of the two possible ones
     2597    radius = Line.endpoints[0]->node->x.DistanceSquared(&OldSphereCenter);
     2598    helper.Scale(sqrt(RADIUS*RADIUS - radius));
     2599    OldSphereCenter.AddVector(&helper);
     2600    OldSphereCenter.SubtractVector(&CircleCenter);
     2601    cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;
     2602
     2603    // construct SearchDirection
     2604    SearchDirection.MakeNormalVector(&T.NormalVector, &CirclePlaneNormal);
     2605    helper.CopyVector(&Line.endpoints[0]->node->x);
     2606    helper.SubtractVector(&ThirdNode->x);
     2607    if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)  // ohoh, SearchDirection points inwards!
     2608      SearchDirection.Scale(-1.);
     2609    SearchDirection.ProjectOntoPlane(&OldSphereCenter);
     2610    SearchDirection.Normalize();
     2611    cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
     2612    if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {  // rotated the wrong way!
     2613      cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl;
     2614    }
     2615
     2616    // add third point
     2617    cout << Verbose(1) << "Looking for third point candidates for triangle ... " << endl;
     2618    Find_third_point_for_Tesselation(T.NormalVector, SearchDirection, OldSphereCenter, &Line, ThirdNode, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC);
     2619
     2620  } else {
     2621    cout << Verbose(1) << "Circumcircle for base line " << Line << " and base triangle " << T << " is too big!" << endl;
     2622  }
     2623
     2624  if (Opt_Candidate == NULL) {
     2625    cerr << "WARNING: Could not find a suitable candidate." << endl;
     2626    return false;
     2627  }
     2628  cout << Verbose(1) << " Optimal candidate is " << *Opt_Candidate << " with circumsphere's center at " << OptCandidateCenter << "." << endl;
     2629
     2630  // check whether all edges of the new triangle still have space for one more triangle (i.e. TriangleCount <2)
     2631  atom *AtomCandidates[3];
     2632  AtomCandidates[0] = Opt_Candidate;
     2633  AtomCandidates[1] = Line.endpoints[0]->node;
     2634  AtomCandidates[2] = Line.endpoints[1]->node;
     2635  bool flag = CheckPresenceOfTriangle(out, AtomCandidates);
     2636
     2637  if (flag) { // if so, add
     2638    AddTrianglePoint(Opt_Candidate, 0);
     2639    AddTrianglePoint(Line.endpoints[0]->node, 1);
     2640    AddTrianglePoint(Line.endpoints[1]->node, 2);
     2641
     2642    AddTriangleLine(TPS[0], TPS[1], 0);
     2643    AddTriangleLine(TPS[0], TPS[2], 1);
     2644    AddTriangleLine(TPS[1], TPS[2], 2);
     2645
     2646    BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     2647    AddTriangleToLines();
     2648
     2649    OptCandidateCenter.Scale(-1.);
     2650    BTS->GetNormalVector(OptCandidateCenter);
     2651    OptCandidateCenter.Scale(-1.);
     2652
     2653    cout << "--> New triangle with " << *BTS << " and normal vector " << BTS->NormalVector << " for this triangle ... " << endl;
     2654    cout << Verbose(1) << "We have "<< TrianglesOnBoundaryCount << " for line " << Line << "." << endl;
     2655  } else { // else, yell and do nothing
     2656    cout << Verbose(1) << "This triangle consisting of ";
     2657    cout << *Opt_Candidate << ", ";
     2658    cout << *Line.endpoints[0]->node << " and ";
     2659    cout << *Line.endpoints[1]->node << " ";
     2660    cout << "is invalid!" << endl;
     2661    return false;
     2662  }
     2663
     2664  if (flag && (DoSingleStepOutput && (TrianglesOnBoundaryCount % 10 == 0))) { // if we have a new triangle and want to output each new triangle configuration
     2665    sprintf(NumberName, "-%04d-%s_%s_%s", TriangleFilesWritten, BTS->endpoints[0]->node->Name, BTS->endpoints[1]->node->Name, BTS->endpoints[2]->node->Name);
     2666    if (DoTecplotOutput) {
     2667      string NameofTempFile(tempbasename);
     2668      NameofTempFile.append(NumberName);
     2669      for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
     2670        NameofTempFile.erase(npos, 1);
     2671      NameofTempFile.append(TecplotSuffix);
     2672      cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
     2673      tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
     2674      write_tecplot_file(out, tempstream, this, mol, TriangleFilesWritten);
     2675      tempstream->close();
     2676      tempstream->flush();
     2677      delete(tempstream);
     2678    }
     2679
     2680    if (DoRaster3DOutput) {
     2681      string NameofTempFile(tempbasename);
     2682      NameofTempFile.append(NumberName);
     2683      for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
     2684        NameofTempFile.erase(npos, 1);
     2685      NameofTempFile.append(Raster3DSuffix);
     2686      cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
     2687      tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
     2688      write_raster3d_file(out, tempstream, this, mol);
     2689      // include the current position of the virtual sphere in the temporary raster3d file
     2690      // make the circumsphere's center absolute again
     2691      helper.CopyVector(&Line.endpoints[0]->node->x);
     2692      helper.AddVector(&Line.endpoints[1]->node->x);
     2693      helper.Scale(0.5);
     2694      OptCandidateCenter.AddVector(&helper);
     2695      Vector *center = mol->DetermineCenterOfAll(out);
     2696      OptCandidateCenter.AddVector(center);
     2697      delete(center);
     2698      // and add to file plus translucency object
     2699      *tempstream << "# current virtual sphere\n";
     2700      *tempstream << "8\n  25.0    0.6     -1.0 -1.0 -1.0     0.2        0 0 0 0\n";
     2701      *tempstream << "2\n  " << OptCandidateCenter.x[0] << " " << OptCandidateCenter.x[1] << " " << OptCandidateCenter.x[2] << "\t" << RADIUS << "\t1 0 0\n";
     2702      *tempstream << "9\n  terminating special property\n";
     2703      tempstream->close();
     2704      tempstream->flush();
     2705      delete(tempstream);
     2706    }
     2707    if (DoTecplotOutput || DoRaster3DOutput)
     2708      TriangleFilesWritten++;
     2709  }
     2710
     2711  cout << Verbose(1) << "End of Find_next_suitable_triangle\n";
     2712  return true;
    27132713};
    27142714
     
    27232723void Find_non_convex_border(ofstream *out, molecule* mol, class Tesselation *Tess, class LinkedCell *LCList, const char *filename, const double RADIUS)
    27242724{
    2725         int N = 0;
    2726         bool freeTess = false;
    2727         *out << Verbose(1) << "Entering search for non convex hull. " << endl;
    2728         if (Tess == NULL) {
    2729                 *out << Verbose(1) << "Allocating Tesselation struct ..." << endl;
    2730                 Tess = new Tesselation;
    2731                 freeTess = true;
    2732         }
    2733         bool freeLC = false;
    2734         LineMap::iterator baseline;
    2735         *out << Verbose(0) << "Begin of Find_non_convex_border\n";
    2736         bool flag = false;      // marks whether we went once through all baselines without finding any without two triangles
    2737         bool failflag = false;
    2738 
    2739         if (LCList == NULL) {
    2740                 LCList = new LinkedCell(mol, 2.*RADIUS);
    2741                 freeLC = true;
    2742         }
    2743 
    2744         Tess->Find_starting_triangle(out, mol, RADIUS, LCList);
    2745 
    2746         baseline = Tess->LinesOnBoundary.begin();
    2747         while ((baseline != Tess->LinesOnBoundary.end()) || (flag)) {
    2748                 if (baseline->second->TrianglesCount == 1) {
    2749                         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.
    2750                         flag = flag || failflag;
    2751                         if (!failflag)
    2752                                 cerr << "WARNING: Find_next_suitable_triangle failed." << endl;
    2753                 } else {
    2754                         cout << Verbose(1) << "Line " << *baseline->second << " has " << baseline->second->TrianglesCount << " triangles adjacent" << endl;
    2755                 }
    2756                 N++;
    2757                 baseline++;
    2758                 if ((baseline == Tess->LinesOnBoundary.end()) && (flag)) {
    2759                         baseline = Tess->LinesOnBoundary.begin();        // restart if we reach end due to newly inserted lines
    2760                         flag = false;
    2761                 }
    2762         }
    2763         if (1) { //failflag) {
    2764                 *out << Verbose(1) << "Writing final tecplot file\n";
    2765                 if (DoTecplotOutput) {
    2766                         string OutputName(filename);
    2767                         OutputName.append(TecplotSuffix);
    2768                         ofstream *tecplot = new ofstream(OutputName.c_str());
    2769                         write_tecplot_file(out, tecplot, Tess, mol, -1);
    2770                         tecplot->close();
    2771                         delete(tecplot);
    2772                 }
    2773                 if (DoRaster3DOutput) {
    2774                         string OutputName(filename);
    2775                         OutputName.append(Raster3DSuffix);
    2776                         ofstream *raster = new ofstream(OutputName.c_str());
    2777                         write_raster3d_file(out, raster, Tess, mol);
    2778                         raster->close();
    2779                         delete(raster);
    2780                 }
    2781         } else {
    2782                 cerr << "ERROR: Could definately not find all necessary triangles!" << endl;
    2783         }
    2784         if (freeTess)
    2785                 delete(Tess);
    2786         if (freeLC)
    2787                 delete(LCList);
    2788         *out << Verbose(0) << "End of Find_non_convex_border\n";
     2725  int N = 0;
     2726  bool freeTess = false;
     2727  *out << Verbose(1) << "Entering search for non convex hull. " << endl;
     2728  if (Tess == NULL) {
     2729    *out << Verbose(1) << "Allocating Tesselation struct ..." << endl;
     2730    Tess = new Tesselation;
     2731    freeTess = true;
     2732  }
     2733  bool freeLC = false;
     2734  LineMap::iterator baseline;
     2735  *out << Verbose(0) << "Begin of Find_non_convex_border\n";
     2736  bool flag = false;  // marks whether we went once through all baselines without finding any without two triangles
     2737  bool failflag = false;
     2738
     2739  if (LCList == NULL) {
     2740    LCList = new LinkedCell(mol, 2.*RADIUS);
     2741    freeLC = true;
     2742  }
     2743
     2744  Tess->Find_starting_triangle(out, mol, RADIUS, LCList);
     2745
     2746  baseline = Tess->LinesOnBoundary.begin();
     2747  while ((baseline != Tess->LinesOnBoundary.end()) || (flag)) {
     2748    if (baseline->second->TrianglesCount == 1) {
     2749      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.
     2750      flag = flag || failflag;
     2751      if (!failflag)
     2752        cerr << "WARNING: Find_next_suitable_triangle failed." << endl;
     2753    } else {
     2754      cout << Verbose(1) << "Line " << *baseline->second << " has " << baseline->second->TrianglesCount << " triangles adjacent" << endl;
     2755    }
     2756    N++;
     2757    baseline++;
     2758    if ((baseline == Tess->LinesOnBoundary.end()) && (flag)) {
     2759      baseline = Tess->LinesOnBoundary.begin();  // restart if we reach end due to newly inserted lines
     2760      flag = false;
     2761    }
     2762  }
     2763  if (1) { //failflag) {
     2764    *out << Verbose(1) << "Writing final tecplot file\n";
     2765    if (DoTecplotOutput) {
     2766      string OutputName(filename);
     2767      OutputName.append(TecplotSuffix);
     2768      ofstream *tecplot = new ofstream(OutputName.c_str());
     2769      write_tecplot_file(out, tecplot, Tess, mol, -1);
     2770      tecplot->close();
     2771      delete(tecplot);
     2772    }
     2773    if (DoRaster3DOutput) {
     2774      string OutputName(filename);
     2775      OutputName.append(Raster3DSuffix);
     2776      ofstream *raster = new ofstream(OutputName.c_str());
     2777      write_raster3d_file(out, raster, Tess, mol);
     2778      raster->close();
     2779      delete(raster);
     2780    }
     2781  } else {
     2782    cerr << "ERROR: Could definately not find all necessary triangles!" << endl;
     2783  }
     2784  if (freeTess)
     2785    delete(Tess);
     2786  if (freeLC)
     2787    delete(LCList);
     2788  *out << Verbose(0) << "End of Find_non_convex_border\n";
    27892789};
    27902790
  • src/boundary.hpp

    r178f92 r437922  
    2727template <typename T> void SetEndpointsOrdered(T endpoints[2], T endpoint1, T endpoint2)
    2828{
    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         }
     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  }
    3636};
    3737
    3838class BoundaryPointSet {
    39         public:
    40                 BoundaryPointSet();
    41                 BoundaryPointSet(atom *Walker);
    42                 ~BoundaryPointSet();
     39  public:
     40    BoundaryPointSet();
     41    BoundaryPointSet(atom *Walker);
     42    ~BoundaryPointSet();
    4343
    44                 void AddLine(class BoundaryLineSet *line);
     44    void AddLine(class BoundaryLineSet *line);
    4545
    46                 LineMap lines;
    47                 int LinesCount;
    48                 atom *node;
    49                 int Nr;
     46    LineMap lines;
     47    int LinesCount;
     48    atom *node;
     49    int Nr;
    5050};
    5151
    5252class BoundaryLineSet {
    53         public:
    54                 BoundaryLineSet();
    55                 BoundaryLineSet(class BoundaryPointSet *Point[2], int number);
    56                 ~BoundaryLineSet();
     53  public:
     54    BoundaryLineSet();
     55    BoundaryLineSet(class BoundaryPointSet *Point[2], int number);
     56    ~BoundaryLineSet();
    5757
    58                 void AddTriangle(class BoundaryTriangleSet *triangle);
     58    void AddTriangle(class BoundaryTriangleSet *triangle);
    5959
    60                 class BoundaryPointSet *endpoints[2];
    61                 TriangleMap triangles;
    62                 int TrianglesCount;
    63                 int Nr;
     60    class BoundaryPointSet *endpoints[2];
     61    TriangleMap triangles;
     62    int TrianglesCount;
     63    int Nr;
    6464};
    6565
    6666class BoundaryTriangleSet {
    67         public:
    68                 BoundaryTriangleSet();
    69                 BoundaryTriangleSet(class BoundaryLineSet *line[3], int number);
    70                 ~BoundaryTriangleSet();
     67  public:
     68    BoundaryTriangleSet();
     69    BoundaryTriangleSet(class BoundaryLineSet *line[3], int number);
     70    ~BoundaryTriangleSet();
    7171
    72                 void GetNormalVector(Vector &NormalVector);
     72    void GetNormalVector(Vector &NormalVector);
    7373
    74                 class BoundaryPointSet *endpoints[3];
    75                 class BoundaryLineSet *lines[3];
    76                 Vector NormalVector;
    77                 int Nr;
     74    class BoundaryPointSet *endpoints[3];
     75    class BoundaryLineSet *lines[3];
     76    Vector NormalVector;
     77    int Nr;
    7878};
    7979
    8080class Tesselation {
    81         public:
     81  public:
    8282
    83                 Tesselation();
    84                 ~Tesselation();
     83    Tesselation();
     84    ~Tesselation();
    8585
    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);
     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);
    9696
    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;
     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;
    108108};
    109109
  • src/builder.cpp

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

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

    r178f92 r437922  
    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;
     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;
    2929};
    3030
     
    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;
     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;
    4747};
    4848
     
    5656bool CreateDataEnergyOrder(class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum)
    5757{
    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;
     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
     
    8989bool CreateDataDeltaEnergyOrder(class EnergyMatrix &Energy, class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum)
    9090{
    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;
     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
     
    190190bool CreateDataDeltaForcesOrderPerAtom(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum)
    191191{
    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;
     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
     
    237237bool CreateDataForcesOrderPerAtom(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum)
    238238{
    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;
     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
     
    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
     
    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
     
    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
     
    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/defs.hpp

    r178f92 r437922  
    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/joiner.cpp

    r178f92 r437922  
    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;
     35  cout << "Joiner" << endl;
     36  cout << "======" << endl;
    3737
    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         }
     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  }
    5454
    55         // Test the given directory
    56         if (!TestParams(argc, argv))
    57                 return 1;
     55  // Test the given directory
     56  if (!TestParams(argc, argv))
     57    return 1;
    5858
    59         // +++++++++++++++++ PARSING +++++++++++++++++++++++++++++++
     59  // +++++++++++++++++ PARSING +++++++++++++++++++++++++++++++
    6060
    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         }
     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  }
    6969
    70         // ---------- Parse the TE Factors into an array -----------------
    71         if (!Energy.ParseIndices()) return 1;
    72         if (Hcorrected) Hcorrection.ParseIndices();
     70  // ---------- Parse the TE Factors into an array -----------------
     71  if (!Energy.ParseIndices()) return 1;
     72  if (Hcorrected) Hcorrection.ParseIndices();
    7373
    74         // ---------- Parse the Force indices into an array ---------------
    75         if (!Force.ParseIndices(argv[1])) return 1;
     74  // ---------- Parse the Force indices into an array ---------------
     75  if (!Force.ParseIndices(argv[1])) return 1;
    7676
    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         }
     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  }
    8282
    83         // ---------- Parse the KeySets into an array ---------------
    84         if (!KeySet.ParseKeySets(argv[1], Force.RowCounter, Force.MatrixCounter)) return 1;
     83  // ---------- Parse the KeySets into an array ---------------
     84  if (!KeySet.ParseKeySets(argv[1], Force.RowCounter, Force.MatrixCounter)) return 1;
    8585
    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         }
     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  }
    9494
    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         }
     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  }
    102102
    103         // +++++++++++++++++ SUMMING +++++++++++++++++++++++++++++++
     103  // +++++++++++++++++ SUMMING +++++++++++++++++++++++++++++++
    104104
    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                 }
     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    }
    127127
    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         }
     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  }
    163163
    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         }
     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  }
    172172
    173         // exit
    174         delete(periode);
    175         Free((void **)&dir, "main: *dir");
    176         cout << "done." << endl;
    177         return 0;
     173  // exit
     174  delete(periode);
     175  Free((void **)&dir, "main: *dir");
     176  cout << "done." << endl;
     177  return 0;
    178178};
    179179
  • src/moleculelist.cpp

    r178f92 r437922  
    527527
    528528  // open file for the force factors
    529   *out << Verbose(1) << "Saving force factors ... ";
     529  *out << Verbose(1) << "Saving  force factors ... ";
    530530  line << path << "/" << FRAGMENTPREFIX << FORCESFILE;
    531531  ForcesFile.open(line.str().c_str(), ios::out);
     
    695695MoleculeLeafClass::MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf = NULL)
    696696{
    697   //    if (Up != NULL)
    698   //            if (Up->DownLeaf == NULL) // are we the first down leaf for the upper leaf?
    699   //                    Up->DownLeaf = this;
    700   //    UpLeaf = Up;
    701   //    DownLeaf = NULL;
     697  //  if (Up != NULL)
     698  //    if (Up->DownLeaf == NULL) // are we the first down leaf for the upper leaf?
     699  //      Up->DownLeaf = this;
     700  //  UpLeaf = Up;
     701  //  DownLeaf = NULL;
    702702  Leaf = NULL;
    703703  previous = PreviousLeaf;
     
    715715MoleculeLeafClass::~MoleculeLeafClass()
    716716{
    717   //    if (DownLeaf != NULL) {// drop leaves further down
    718   //            MoleculeLeafClass *Walker = DownLeaf;
    719   //            MoleculeLeafClass *Next;
    720   //            do {
    721   //                    Next = Walker->NextLeaf;
    722   //                    delete(Walker);
    723   //                    Walker = Next;
    724   //            } while (Walker != NULL);
    725   //            // Last Walker sets DownLeaf automatically to NULL
    726   //    }
     717  //  if (DownLeaf != NULL) {// drop leaves further down
     718  //    MoleculeLeafClass *Walker = DownLeaf;
     719  //    MoleculeLeafClass *Next;
     720  //    do {
     721  //      Next = Walker->NextLeaf;
     722  //      delete(Walker);
     723  //      Walker = Next;
     724  //    } while (Walker != NULL);
     725  //    // Last Walker sets DownLeaf automatically to NULL
     726  //  }
    727727  // remove the leaf itself
    728728  if (Leaf != NULL) {
     
    733733  if (previous != NULL)
    734734    previous->next = next;
    735   //    } else { // we are first in list (connects to UpLeaf->DownLeaf)
    736   //            if ((NextLeaf != NULL) && (NextLeaf->UpLeaf == NULL))
    737   //                    NextLeaf->UpLeaf = UpLeaf;      // either null as we are top level or the upleaf of the first node
    738   //            if (UpLeaf != NULL)
    739   //                    UpLeaf->DownLeaf = NextLeaf;    // either null as we are only leaf or NextLeaf if we are just the first
    740   //    }
    741   //    UpLeaf = NULL;
     735  //  } else { // we are first in list (connects to UpLeaf->DownLeaf)
     736  //    if ((NextLeaf != NULL) && (NextLeaf->UpLeaf == NULL))
     737  //      NextLeaf->UpLeaf = UpLeaf;  // either null as we are top level or the upleaf of the first node
     738  //    if (UpLeaf != NULL)
     739  //      UpLeaf->DownLeaf = NextLeaf;  // either null as we are only leaf or NextLeaf if we are just the first
     740  //  }
     741  //  UpLeaf = NULL;
    742742  if (next != NULL) // are we last in list
    743743    next->previous = previous;
  • src/molecules.cpp

    r178f92 r437922  
    1616double LSQ (const gsl_vector * x, void * params)
    1717{
    18         double sum = 0.;
    19         struct LSQ_params *par = (struct LSQ_params *)params;
    20         Vector **vectors = par->vectors;
    21         int num = par->num;
    22 
    23         for (int i=num;i--;) {
    24                 for(int j=NDIM;j--;)
    25                         sum += (gsl_vector_get(x,j) - (vectors[i])->x[j])*(gsl_vector_get(x,j) - (vectors[i])->x[j]);
    26         }
    27 
    28         return sum;
     18  double sum = 0.;
     19  struct LSQ_params *par = (struct LSQ_params *)params;
     20  Vector **vectors = par->vectors;
     21  int num = par->num;
     22
     23  for (int i=num;i--;) {
     24    for(int j=NDIM;j--;)
     25      sum += (gsl_vector_get(x,j) - (vectors[i])->x[j])*(gsl_vector_get(x,j) - (vectors[i])->x[j]);
     26  }
     27
     28  return sum;
    2929};
    3030
     
    3636molecule::molecule(periodentafel *teil)
    3737{
    38         // init atom chain list
    39         start = new atom;
    40         end = new atom;
    41         start->father = NULL;
    42         end->father = NULL;
    43         link(start,end);
    44         // init bond chain list
    45         first = new bond(start, end, 1, -1);
    46         last = new bond(start, end, 1, -1);
    47         link(first,last);
    48         // other stuff
    49         MDSteps = 0;
    50         last_atom = 0;
    51         elemente = teil;
    52         AtomCount = 0;
    53         BondCount = 0;
    54         NoNonBonds = 0;
    55         NoNonHydrogen = 0;
    56         NoCyclicBonds = 0;
    57         ListOfBondsPerAtom = NULL;
    58         NumberOfBondsPerAtom = NULL;
    59         ElementCount = 0;
    60         for(int i=MAX_ELEMENTS;i--;)
    61                 ElementsInMolecule[i] = 0;
    62         cell_size[0] = cell_size[2] = cell_size[5]= 20.;
    63         cell_size[1] = cell_size[3] = cell_size[4]= 0.;
    64         strcpy(name,"none");
    65         IndexNr  = -1;
    66         ActiveFlag = false;
     38  // init atom chain list
     39  start = new atom;
     40  end = new atom;
     41  start->father = NULL;
     42  end->father = NULL;
     43  link(start,end);
     44  // init bond chain list
     45  first = new bond(start, end, 1, -1);
     46  last = new bond(start, end, 1, -1);
     47  link(first,last);
     48  // other stuff
     49  MDSteps = 0;
     50  last_atom = 0;
     51  elemente = teil;
     52  AtomCount = 0;
     53  BondCount = 0;
     54  NoNonBonds = 0;
     55  NoNonHydrogen = 0;
     56  NoCyclicBonds = 0;
     57  ListOfBondsPerAtom = NULL;
     58  NumberOfBondsPerAtom = NULL;
     59  ElementCount = 0;
     60  for(int i=MAX_ELEMENTS;i--;)
     61    ElementsInMolecule[i] = 0;
     62  cell_size[0] = cell_size[2] = cell_size[5]= 20.;
     63  cell_size[1] = cell_size[3] = cell_size[4]= 0.;
     64  strcpy(name,"none");
     65  IndexNr  = -1;
     66  ActiveFlag = false;
    6767};
    6868
     
    7272molecule::~molecule()
    7373{
    74         if (ListOfBondsPerAtom != NULL)
    75                 for(int i=AtomCount;i--;)
    76                         Free((void **)&ListOfBondsPerAtom[i], "molecule::~molecule: ListOfBondsPerAtom[i]");
    77         Free((void **)&ListOfBondsPerAtom, "molecule::~molecule: ListOfBondsPerAtom");
    78         Free((void **)&NumberOfBondsPerAtom, "molecule::~molecule: NumberOfBondsPerAtom");
    79         CleanupMolecule();
    80         delete(first);
    81         delete(last);
    82         delete(end);
    83         delete(start);
     74  if (ListOfBondsPerAtom != NULL)
     75    for(int i=AtomCount;i--;)
     76      Free((void **)&ListOfBondsPerAtom[i], "molecule::~molecule: ListOfBondsPerAtom[i]");
     77  Free((void **)&ListOfBondsPerAtom, "molecule::~molecule: ListOfBondsPerAtom");
     78  Free((void **)&NumberOfBondsPerAtom, "molecule::~molecule: NumberOfBondsPerAtom");
     79  CleanupMolecule();
     80  delete(first);
     81  delete(last);
     82  delete(end);
     83  delete(start);
    8484};
    8585
     
    9191bool molecule::AddAtom(atom *pointer)
    9292{
    93         if (pointer != NULL) {
    94                 pointer->sort = &pointer->nr;
    95                 pointer->nr = last_atom++;      // increase number within molecule
    96                 AtomCount++;
    97                 if (pointer->type != NULL) {
    98                         if (ElementsInMolecule[pointer->type->Z] == 0)
    99                                 ElementCount++;
    100                         ElementsInMolecule[pointer->type->Z]++; // increase number of elements
    101                         if (pointer->type->Z != 1)
    102                                 NoNonHydrogen++;
    103                         if (pointer->Name == NULL) {
    104                                 Free((void **)&pointer->Name, "molecule::AddAtom: *pointer->Name");
    105                                 pointer->Name = (char *) Malloc(sizeof(char)*6, "molecule::AddAtom: *pointer->Name");
    106                                 sprintf(pointer->Name, "%2s%02d", pointer->type->symbol, pointer->nr+1);
    107                         }
    108                 }
    109                 return add(pointer, end);
    110         } else
    111                 return false;
     93  if (pointer != NULL) {
     94    pointer->sort = &pointer->nr;
     95    pointer->nr = last_atom++;  // increase number within molecule
     96    AtomCount++;
     97    if (pointer->type != NULL) {
     98      if (ElementsInMolecule[pointer->type->Z] == 0)
     99        ElementCount++;
     100      ElementsInMolecule[pointer->type->Z]++; // increase number of elements
     101      if (pointer->type->Z != 1)
     102        NoNonHydrogen++;
     103      if (pointer->Name == NULL) {
     104        Free((void **)&pointer->Name, "molecule::AddAtom: *pointer->Name");
     105        pointer->Name = (char *) Malloc(sizeof(char)*6, "molecule::AddAtom: *pointer->Name");
     106        sprintf(pointer->Name, "%2s%02d", pointer->type->symbol, pointer->nr+1);
     107      }
     108    }
     109    return add(pointer, end);
     110  } else
     111    return false;
    112112};
    113113
     
    119119atom * molecule::AddCopyAtom(atom *pointer)
    120120{
    121         if (pointer != NULL) {
    122                 atom *walker = new atom();
    123                 walker->type = pointer->type;   // copy element of atom
    124                 walker->x.CopyVector(&pointer->x); // copy coordination
    125                 walker->v.CopyVector(&pointer->v); // copy velocity
    126                 walker->FixedIon = pointer->FixedIon;
    127                 walker->sort = &walker->nr;
    128                 walker->nr = last_atom++;       // increase number within molecule
    129                 walker->father = pointer; //->GetTrueFather();
    130                 walker->Name = (char *) Malloc(sizeof(char)*strlen(pointer->Name)+1, "molecule::AddCopyAtom: *Name");
    131                 strcpy (walker->Name, pointer->Name);
    132                 add(walker, end);
    133                 if ((pointer->type != NULL) && (pointer->type->Z != 1))
    134                         NoNonHydrogen++;
    135                 AtomCount++;
    136                 return walker;
    137         } else
    138                 return NULL;
     121  if (pointer != NULL) {
     122    atom *walker = new atom();
     123    walker->type = pointer->type;  // copy element of atom
     124    walker->x.CopyVector(&pointer->x); // copy coordination
     125    walker->v.CopyVector(&pointer->v); // copy velocity
     126    walker->FixedIon = pointer->FixedIon;
     127    walker->sort = &walker->nr;
     128    walker->nr = last_atom++;  // increase number within molecule
     129    walker->father = pointer; //->GetTrueFather();
     130    walker->Name = (char *) Malloc(sizeof(char)*strlen(pointer->Name)+1, "molecule::AddCopyAtom: *Name");
     131    strcpy (walker->Name, pointer->Name);
     132    add(walker, end);
     133    if ((pointer->type != NULL) && (pointer->type->Z != 1))
     134      NoNonHydrogen++;
     135    AtomCount++;
     136    return walker;
     137  } else
     138    return NULL;
    139139};
    140140
     
    144144 * -# Single Bond: Simply add new atom with bond distance rescaled to typical hydrogen one
    145145 * -# Double Bond: Here, we need the **BondList of the \a *origin atom, by scanning for the other bonds instead of
    146  *              *Bond, we use the through these connected atoms to determine the plane they lie in, vector::MakeNormalvector().
    147  *              The orthonormal vector to this plane along with the vector in *Bond direction determines the plane the two
    148  *              replacing hydrogens shall lie in. Now, all remains to do is take the usual hydrogen double bond angle for the
    149  *              element of *origin and form the sin/cos admixture of both plane vectors for the new coordinates of the two
    150  *              hydrogens forming this angle with *origin.
     146 *    *Bond, we use the through these connected atoms to determine the plane they lie in, vector::MakeNormalvector().
     147 *    The orthonormal vector to this plane along with the vector in *Bond direction determines the plane the two
     148 *    replacing hydrogens shall lie in. Now, all remains to do is take the usual hydrogen double bond angle for the
     149 *    element of *origin and form the sin/cos admixture of both plane vectors for the new coordinates of the two
     150 *    hydrogens forming this angle with *origin.
    151151 * -# 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
    152  *              triangle formed by the to be added hydrogens are not equal to the typical bond distance \f$l\f$ but have to be
    153  *              determined from the typical angle \f$\alpha\f$ for a hydrogen triple connected to the element of *origin):
    154  *              We have the height \f$d\f$ as the vector in *Bond direction (from triangle C1-H1-H2).
    155  *              \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 )}}
    156  *              \f]
    157  *              vector::GetNormalvector() creates one orthonormal vector from this *Bond vector and vector::MakeNormalvector creates
    158  *              the third one from the former two vectors. The latter ones form the plane of the base triangle mentioned above.
    159  *              The lengths for these are \f$f\f$ and \f$g\f$ (from triangle H1-H2-(center of H1-H2-H3)) with knowledge that
    160  *              the median lines in an isosceles triangle meet in the center point with a ratio 2:1.
    161  *              \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2}
    162  *              \f]
    163  *              as the coordination of all three atoms in the coordinate system of these three vectors:
    164  *              \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$.
     152 *    triangle formed by the to be added hydrogens are not equal to the typical bond distance \f$l\f$ but have to be
     153 *    determined from the typical angle \f$\alpha\f$ for a hydrogen triple connected to the element of *origin):
     154 *    We have the height \f$d\f$ as the vector in *Bond direction (from triangle C1-H1-H2).
     155 *    \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 )}}
     156 *    \f]
     157 *    vector::GetNormalvector() creates one orthonormal vector from this *Bond vector and vector::MakeNormalvector creates
     158 *    the third one from the former two vectors. The latter ones form the plane of the base triangle mentioned above.
     159 *    The lengths for these are \f$f\f$ and \f$g\f$ (from triangle H1-H2-(center of H1-H2-H3)) with knowledge that
     160 *    the median lines in an isosceles triangle meet in the center point with a ratio 2:1.
     161 *    \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2}
     162 *    \f]
     163 *    as the coordination of all three atoms in the coordinate system of these three vectors:
     164 *    \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$.
    165165 *
    166166 * \param *out output stream for debugging
     
    170170 * \param *replacement pointer to the atom which shall be copied as a hydrogen atom in this molecule
    171171 * \param **BondList list of bonds \a *replacement has (necessary to determine plane for double and triple bonds)
    172  * \param NumBond       number of bonds in \a **BondList
     172 * \param NumBond  number of bonds in \a **BondList
    173173 * \param isAngstroem whether the coordination of the given atoms is in AtomicLength (false) or Angstrom(true)
    174174 * \return number of atoms added, if < bond::BondDegree then something went wrong
     
    177177bool molecule::AddHydrogenReplacementAtom(ofstream *out, bond *TopBond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem)
    178178{
    179         double bondlength;      // bond length of the bond to be replaced/cut
    180         double bondangle;       // bond angle of the bond to be replaced/cut
    181         double BondRescale;      // rescale value for the hydrogen bond length
    182         bool AllWentWell = true;                // flag gathering the boolean return value of molecule::AddAtom and other functions, as return value on exit
    183         bond *FirstBond = NULL, *SecondBond = NULL; // Other bonds in double bond case to determine "other" plane
    184         atom *FirstOtherAtom = NULL, *SecondOtherAtom = NULL, *ThirdOtherAtom = NULL; // pointer to hydrogen atoms to be added
    185         double b,l,d,f,g, alpha, factors[NDIM];         // hold temporary values in triple bond case for coordination determination
    186         Vector Orthovector1, Orthovector2;      // temporary vectors in coordination construction
    187         Vector InBondvector;            // vector in direction of *Bond
    188         bond *Binder = NULL;
    189         double *matrix;
    190 
    191 //      *out << Verbose(3) << "Begin of AddHydrogenReplacementAtom." << endl;
    192         // create vector in direction of bond
    193         InBondvector.CopyVector(&TopReplacement->x);
    194         InBondvector.SubtractVector(&TopOrigin->x);
    195         bondlength = InBondvector.Norm();
    196 
    197         // is greater than typical bond distance? Then we have to correct periodically
    198         // the problem is not the H being out of the box, but InBondvector have the wrong direction
    199         // due to TopReplacement or Origin being on the wrong side!
    200         if (bondlength > BondDistance) {
    201 //              *out << Verbose(4) << "InBondvector is: ";
    202 //              InBondvector.Output(out);
    203 //              *out << endl;
    204                 Orthovector1.Zero();
    205                 for (int i=NDIM;i--;) {
    206                         l = TopReplacement->x.x[i] - TopOrigin->x.x[i];
    207                         if (fabs(l) > BondDistance) { // is component greater than bond distance
    208                                 Orthovector1.x[i] = (l < 0) ? -1. : +1.;
    209                         } // (signs are correct, was tested!)
    210                 }
    211                 matrix = ReturnFullMatrixforSymmetric(cell_size);
    212                 Orthovector1.MatrixMultiplication(matrix);
    213                 InBondvector.SubtractVector(&Orthovector1); // subtract just the additional translation
    214                 Free((void **)&matrix, "molecule::AddHydrogenReplacementAtom: *matrix");
    215                 bondlength = InBondvector.Norm();
    216 //              *out << Verbose(4) << "Corrected InBondvector is now: ";
    217 //              InBondvector.Output(out);
    218 //              *out << endl;
    219         } // periodic correction finished
    220 
    221         InBondvector.Normalize();
    222         // get typical bond length and store as scale factor for later
    223         BondRescale = TopOrigin->type->HBondDistance[TopBond->BondDegree-1];
    224         if (BondRescale == -1) {
    225                 cerr << Verbose(3) << "ERROR: There is no typical hydrogen bond distance in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl;
    226                 return false;
    227                 BondRescale = bondlength;
    228         } else {
    229                 if (!IsAngstroem)
    230                         BondRescale /= (1.*AtomicLengthToAngstroem);
    231         }
    232 
    233         // discern single, double and triple bonds
    234         switch(TopBond->BondDegree) {
    235                 case 1:
    236                         FirstOtherAtom = new atom();            // new atom
    237                         FirstOtherAtom->type = elemente->FindElement(1);        // element is Hydrogen
    238                         FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
    239                         FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
    240                         if (TopReplacement->type->Z == 1) { // neither rescale nor replace if it's already hydrogen
    241                                 FirstOtherAtom->father = TopReplacement;
    242                                 BondRescale = bondlength;
    243                         } else {
    244                                 FirstOtherAtom->father = NULL;  // if we replace hydrogen, we mark it as our father, otherwise we are just an added hydrogen with no father
    245                         }
    246                         InBondvector.Scale(&BondRescale);        // rescale the distance vector to Hydrogen bond length
    247                         FirstOtherAtom->x.CopyVector(&TopOrigin->x); // set coordination to origin ...
    248                         FirstOtherAtom->x.AddVector(&InBondvector);     // ... and add distance vector to replacement atom
    249                         AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
    250 //                      *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
    251 //                      FirstOtherAtom->x.Output(out);
    252 //                      *out << endl;
    253                         Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);
    254                         Binder->Cyclic = false;
    255                         Binder->Type = TreeEdge;
    256                         break;
    257                 case 2:
    258                         // determine two other bonds (warning if there are more than two other) plus valence sanity check
    259                         for (int i=0;i<NumBond;i++) {
    260                                 if (BondList[i] != TopBond) {
    261                                         if (FirstBond == NULL) {
    262                                                 FirstBond = BondList[i];
    263                                                 FirstOtherAtom = BondList[i]->GetOtherAtom(TopOrigin);
    264                                         } else if (SecondBond == NULL) {
    265                                                 SecondBond = BondList[i];
    266                                                 SecondOtherAtom = BondList[i]->GetOtherAtom(TopOrigin);
    267                                         } else {
    268                                                 *out << Verbose(3) << "WARNING: Detected more than four bonds for atom " << TopOrigin->Name;
    269                                         }
    270                                 }
    271                         }
    272                         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)
    273                                 SecondBond = TopBond;
    274                                 SecondOtherAtom = TopReplacement;
    275                         }
    276                         if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all
    277 //                              *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;
    278 
    279                                 // determine the plane of these two with the *origin
    280                                 AllWentWell = AllWentWell && Orthovector1.MakeNormalVector(&TopOrigin->x, &FirstOtherAtom->x, &SecondOtherAtom->x);
    281                         } else {
    282                                 Orthovector1.GetOneNormalVector(&InBondvector);
    283                         }
    284                         //*out << Verbose(3)<< "Orthovector1: ";
    285                         //Orthovector1.Output(out);
    286                         //*out << endl;
    287                         // orthogonal vector and bond vector between origin and replacement form the new plane
    288                         Orthovector1.MakeNormalVector(&InBondvector);
    289                         Orthovector1.Normalize();
    290                         //*out << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl;
    291 
    292                         // create the two Hydrogens ...
    293                         FirstOtherAtom = new atom();
    294                         SecondOtherAtom = new atom();
    295                         FirstOtherAtom->type = elemente->FindElement(1);
    296                         SecondOtherAtom->type = elemente->FindElement(1);
    297                         FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
    298                         FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
    299                         SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
    300                         SecondOtherAtom->FixedIon = TopReplacement->FixedIon;
    301                         FirstOtherAtom->father = NULL;  // we are just an added hydrogen with no father
    302                         SecondOtherAtom->father = NULL; //      we are just an added hydrogen with no father
    303                         bondangle = TopOrigin->type->HBondAngle[1];
    304                         if (bondangle == -1) {
    305                                 *out << Verbose(3) << "ERROR: There is no typical hydrogen bond angle in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl;
    306                                 return false;
    307                                 bondangle = 0;
    308                         }
    309                         bondangle *= M_PI/180./2.;
    310 //                      *out << Verbose(3) << "ReScaleCheck: InBondvector ";
    311 //                      InBondvector.Output(out);
    312 //                      *out << endl;
    313 //                      *out << Verbose(3) << "ReScaleCheck: Orthovector ";
    314 //                      Orthovector1.Output(out);
    315 //                      *out << endl;
    316 //                      *out << Verbose(3) << "Half the bond angle is " << bondangle << ", sin and cos of it: " << sin(bondangle) << ", " << cos(bondangle) << endl;
    317                         FirstOtherAtom->x.Zero();
    318                         SecondOtherAtom->x.Zero();
    319                         for(int i=NDIM;i--;) { // rotate by half the bond angle in both directions (InBondvector is bondangle = 0 direction)
    320                                 FirstOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (sin(bondangle));
    321                                 SecondOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (-sin(bondangle));
    322                         }
    323                         FirstOtherAtom->x.Scale(&BondRescale);  // rescale by correct BondDistance
    324                         SecondOtherAtom->x.Scale(&BondRescale);
    325                         //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl;
    326                         for(int i=NDIM;i--;) { // and make relative to origin atom
    327                                 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i];
    328                                 SecondOtherAtom->x.x[i] += TopOrigin->x.x[i];
    329                         }
    330                         // ... and add to molecule
    331                         AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
    332                         AllWentWell = AllWentWell && AddAtom(SecondOtherAtom);
    333 //                      *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
    334 //                      FirstOtherAtom->x.Output(out);
    335 //                      *out << endl;
    336 //                      *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: ";
    337 //                      SecondOtherAtom->x.Output(out);
    338 //                      *out << endl;
    339                         Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);
    340                         Binder->Cyclic = false;
    341                         Binder->Type = TreeEdge;
    342                         Binder = AddBond(BottomOrigin, SecondOtherAtom, 1);
    343                         Binder->Cyclic = false;
    344                         Binder->Type = TreeEdge;
    345                         break;
    346                 case 3:
    347                         // take the "usual" tetraoidal angle and add the three Hydrogen in direction of the bond (height of the tetraoid)
    348                         FirstOtherAtom = new atom();
    349                         SecondOtherAtom = new atom();
    350                         ThirdOtherAtom = new atom();
    351                         FirstOtherAtom->type = elemente->FindElement(1);
    352                         SecondOtherAtom->type = elemente->FindElement(1);
    353                         ThirdOtherAtom->type = elemente->FindElement(1);
    354                         FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
    355                         FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
    356                         SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
    357                         SecondOtherAtom->FixedIon = TopReplacement->FixedIon;
    358                         ThirdOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
    359                         ThirdOtherAtom->FixedIon = TopReplacement->FixedIon;
    360                         FirstOtherAtom->father = NULL;  //      we are just an added hydrogen with no father
    361                         SecondOtherAtom->father = NULL; //      we are just an added hydrogen with no father
    362                         ThirdOtherAtom->father = NULL;  //      we are just an added hydrogen with no father
    363 
    364                         // we need to vectors orthonormal the InBondvector
    365                         AllWentWell = AllWentWell && Orthovector1.GetOneNormalVector(&InBondvector);
    366 //                      *out << Verbose(3) << "Orthovector1: ";
    367 //                      Orthovector1.Output(out);
    368 //                      *out << endl;
    369                         AllWentWell = AllWentWell && Orthovector2.MakeNormalVector(&InBondvector, &Orthovector1);
    370 //                      *out << Verbose(3) << "Orthovector2: ";
    371 //                      Orthovector2.Output(out);
    372 //                      *out << endl;
    373 
    374                         // create correct coordination for the three atoms
    375                         alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.;  // retrieve triple bond angle from database
    376                         l = BondRescale;                                // desired bond length
    377                         b = 2.*l*sin(alpha);            // base length of isosceles triangle
    378                         d = l*sqrt(cos(alpha)*cos(alpha) - sin(alpha)*sin(alpha)/3.);    // length for InBondvector
    379                         f = b/sqrt(3.); // length for Orthvector1
    380                         g = b/2.;                                // length for Orthvector2
    381 //                      *out << Verbose(3) << "Bond length and half-angle: " << l << ", " << alpha << "\t (b,d,f,g) = " << b << ", " << d << ", " << f << ", " << g << ", " << endl;
    382 //                      *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;
    383                         factors[0] = d;
    384                         factors[1] = f;
    385                         factors[2] = 0.;
    386                         FirstOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);
    387                         factors[1] = -0.5*f;
    388                         factors[2] = g;
    389                         SecondOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);
    390                         factors[2] = -g;
    391                         ThirdOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);
    392 
    393                         // rescale each to correct BondDistance
    394 //                      FirstOtherAtom->x.Scale(&BondRescale);
    395 //                      SecondOtherAtom->x.Scale(&BondRescale);
    396 //                      ThirdOtherAtom->x.Scale(&BondRescale);
    397 
    398                         // and relative to *origin atom
    399                         FirstOtherAtom->x.AddVector(&TopOrigin->x);
    400                         SecondOtherAtom->x.AddVector(&TopOrigin->x);
    401                         ThirdOtherAtom->x.AddVector(&TopOrigin->x);
    402 
    403                         // ... and add to molecule
    404                         AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
    405                         AllWentWell = AllWentWell && AddAtom(SecondOtherAtom);
    406                         AllWentWell = AllWentWell && AddAtom(ThirdOtherAtom);
    407 //                      *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
    408 //                      FirstOtherAtom->x.Output(out);
    409 //                      *out << endl;
    410 //                      *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: ";
    411 //                      SecondOtherAtom->x.Output(out);
    412 //                      *out << endl;
    413 //                      *out << Verbose(4) << "Added " << *ThirdOtherAtom << " at: ";
    414 //                      ThirdOtherAtom->x.Output(out);
    415 //                      *out << endl;
    416                         Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);
    417                         Binder->Cyclic = false;
    418                         Binder->Type = TreeEdge;
    419                         Binder = AddBond(BottomOrigin, SecondOtherAtom, 1);
    420                         Binder->Cyclic = false;
    421                         Binder->Type = TreeEdge;
    422                         Binder = AddBond(BottomOrigin, ThirdOtherAtom, 1);
    423                         Binder->Cyclic = false;
    424                         Binder->Type = TreeEdge;
    425                         break;
    426                 default:
    427                         cerr << "ERROR: BondDegree does not state single, double or triple bond!" << endl;
    428                         AllWentWell = false;
    429                         break;
    430         }
    431 
    432 //      *out << Verbose(3) << "End of AddHydrogenReplacementAtom." << endl;
    433         return AllWentWell;
     179  double bondlength;  // bond length of the bond to be replaced/cut
     180  double bondangle;  // bond angle of the bond to be replaced/cut
     181  double BondRescale;  // rescale value for the hydrogen bond length
     182  bool AllWentWell = true;    // flag gathering the boolean return value of molecule::AddAtom and other functions, as return value on exit
     183  bond *FirstBond = NULL, *SecondBond = NULL; // Other bonds in double bond case to determine "other" plane
     184  atom *FirstOtherAtom = NULL, *SecondOtherAtom = NULL, *ThirdOtherAtom = NULL; // pointer to hydrogen atoms to be added
     185  double b,l,d,f,g, alpha, factors[NDIM];    // hold temporary values in triple bond case for coordination determination
     186  Vector Orthovector1, Orthovector2;  // temporary vectors in coordination construction
     187  Vector InBondvector;    // vector in direction of *Bond
     188  bond *Binder = NULL;
     189  double *matrix;
     190
     191//  *out << Verbose(3) << "Begin of AddHydrogenReplacementAtom." << endl;
     192  // create vector in direction of bond
     193  InBondvector.CopyVector(&TopReplacement->x);
     194  InBondvector.SubtractVector(&TopOrigin->x);
     195  bondlength = InBondvector.Norm();
     196
     197  // is greater than typical bond distance? Then we have to correct periodically
     198  // the problem is not the H being out of the box, but InBondvector have the wrong direction
     199  // due to TopReplacement or Origin being on the wrong side!
     200  if (bondlength > BondDistance) {
     201//    *out << Verbose(4) << "InBondvector is: ";
     202//    InBondvector.Output(out);
     203//    *out << endl;
     204    Orthovector1.Zero();
     205    for (int i=NDIM;i--;) {
     206      l = TopReplacement->x.x[i] - TopOrigin->x.x[i];
     207      if (fabs(l) > BondDistance) { // is component greater than bond distance
     208        Orthovector1.x[i] = (l < 0) ? -1. : +1.;
     209      } // (signs are correct, was tested!)
     210    }
     211    matrix = ReturnFullMatrixforSymmetric(cell_size);
     212    Orthovector1.MatrixMultiplication(matrix);
     213    InBondvector.SubtractVector(&Orthovector1); // subtract just the additional translation
     214    Free((void **)&matrix, "molecule::AddHydrogenReplacementAtom: *matrix");
     215    bondlength = InBondvector.Norm();
     216//    *out << Verbose(4) << "Corrected InBondvector is now: ";
     217//    InBondvector.Output(out);
     218//    *out << endl;
     219  } // periodic correction finished
     220
     221  InBondvector.Normalize();
     222  // get typical bond length and store as scale factor for later
     223  BondRescale = TopOrigin->type->HBondDistance[TopBond->BondDegree-1];
     224  if (BondRescale == -1) {
     225    cerr << Verbose(3) << "ERROR: There is no typical hydrogen bond distance in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl;
     226    return false;
     227    BondRescale = bondlength;
     228  } else {
     229    if (!IsAngstroem)
     230      BondRescale /= (1.*AtomicLengthToAngstroem);
     231  }
     232
     233  // discern single, double and triple bonds
     234  switch(TopBond->BondDegree) {
     235    case 1:
     236      FirstOtherAtom = new atom();    // new atom
     237      FirstOtherAtom->type = elemente->FindElement(1);  // element is Hydrogen
     238      FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
     239      FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
     240      if (TopReplacement->type->Z == 1) { // neither rescale nor replace if it's already hydrogen
     241        FirstOtherAtom->father = TopReplacement;
     242        BondRescale = bondlength;
     243      } else {
     244        FirstOtherAtom->father = NULL;  // if we replace hydrogen, we mark it as our father, otherwise we are just an added hydrogen with no father
     245      }
     246      InBondvector.Scale(&BondRescale);  // rescale the distance vector to Hydrogen bond length
     247      FirstOtherAtom->x.CopyVector(&TopOrigin->x); // set coordination to origin ...
     248      FirstOtherAtom->x.AddVector(&InBondvector);  // ... and add distance vector to replacement atom
     249      AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
     250//      *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
     251//      FirstOtherAtom->x.Output(out);
     252//      *out << endl;
     253      Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);
     254      Binder->Cyclic = false;
     255      Binder->Type = TreeEdge;
     256      break;
     257    case 2:
     258      // determine two other bonds (warning if there are more than two other) plus valence sanity check
     259      for (int i=0;i<NumBond;i++) {
     260        if (BondList[i] != TopBond) {
     261          if (FirstBond == NULL) {
     262            FirstBond = BondList[i];
     263            FirstOtherAtom = BondList[i]->GetOtherAtom(TopOrigin);
     264          } else if (SecondBond == NULL) {
     265            SecondBond = BondList[i];
     266            SecondOtherAtom = BondList[i]->GetOtherAtom(TopOrigin);
     267          } else {
     268            *out << Verbose(3) << "WARNING: Detected more than four bonds for atom " << TopOrigin->Name;
     269          }
     270        }
     271      }
     272      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)
     273        SecondBond = TopBond;
     274        SecondOtherAtom = TopReplacement;
     275      }
     276      if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all
     277//        *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;
     278
     279        // determine the plane of these two with the *origin
     280        AllWentWell = AllWentWell && Orthovector1.MakeNormalVector(&TopOrigin->x, &FirstOtherAtom->x, &SecondOtherAtom->x);
     281      } else {
     282        Orthovector1.GetOneNormalVector(&InBondvector);
     283      }
     284      //*out << Verbose(3)<< "Orthovector1: ";
     285      //Orthovector1.Output(out);
     286      //*out << endl;
     287      // orthogonal vector and bond vector between origin and replacement form the new plane
     288      Orthovector1.MakeNormalVector(&InBondvector);
     289      Orthovector1.Normalize();
     290      //*out << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl;
     291
     292      // create the two Hydrogens ...
     293      FirstOtherAtom = new atom();
     294      SecondOtherAtom = new atom();
     295      FirstOtherAtom->type = elemente->FindElement(1);
     296      SecondOtherAtom->type = elemente->FindElement(1);
     297      FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
     298      FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
     299      SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
     300      SecondOtherAtom->FixedIon = TopReplacement->FixedIon;
     301      FirstOtherAtom->father = NULL;  // we are just an added hydrogen with no father
     302      SecondOtherAtom->father = NULL;  //  we are just an added hydrogen with no father
     303      bondangle = TopOrigin->type->HBondAngle[1];
     304      if (bondangle == -1) {
     305        *out << Verbose(3) << "ERROR: There is no typical hydrogen bond angle in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl;
     306        return false;
     307        bondangle = 0;
     308      }
     309      bondangle *= M_PI/180./2.;
     310//      *out << Verbose(3) << "ReScaleCheck: InBondvector ";
     311//      InBondvector.Output(out);
     312//      *out << endl;
     313//      *out << Verbose(3) << "ReScaleCheck: Orthovector ";
     314//      Orthovector1.Output(out);
     315//      *out << endl;
     316//      *out << Verbose(3) << "Half the bond angle is " << bondangle << ", sin and cos of it: " << sin(bondangle) << ", " << cos(bondangle) << endl;
     317      FirstOtherAtom->x.Zero();
     318      SecondOtherAtom->x.Zero();
     319      for(int i=NDIM;i--;) { // rotate by half the bond angle in both directions (InBondvector is bondangle = 0 direction)
     320        FirstOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (sin(bondangle));
     321        SecondOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (-sin(bondangle));
     322      }
     323      FirstOtherAtom->x.Scale(&BondRescale);  // rescale by correct BondDistance
     324      SecondOtherAtom->x.Scale(&BondRescale);
     325      //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl;
     326      for(int i=NDIM;i--;) { // and make relative to origin atom
     327        FirstOtherAtom->x.x[i] += TopOrigin->x.x[i];
     328        SecondOtherAtom->x.x[i] += TopOrigin->x.x[i];
     329      }
     330      // ... and add to molecule
     331      AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
     332      AllWentWell = AllWentWell && AddAtom(SecondOtherAtom);
     333//      *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
     334//      FirstOtherAtom->x.Output(out);
     335//      *out << endl;
     336//      *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: ";
     337//      SecondOtherAtom->x.Output(out);
     338//      *out << endl;
     339      Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);
     340      Binder->Cyclic = false;
     341      Binder->Type = TreeEdge;
     342      Binder = AddBond(BottomOrigin, SecondOtherAtom, 1);
     343      Binder->Cyclic = false;
     344      Binder->Type = TreeEdge;
     345      break;
     346    case 3:
     347      // take the "usual" tetraoidal angle and add the three Hydrogen in direction of the bond (height of the tetraoid)
     348      FirstOtherAtom = new atom();
     349      SecondOtherAtom = new atom();
     350      ThirdOtherAtom = new atom();
     351      FirstOtherAtom->type = elemente->FindElement(1);
     352      SecondOtherAtom->type = elemente->FindElement(1);
     353      ThirdOtherAtom->type = elemente->FindElement(1);
     354      FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
     355      FirstOtherAtom->FixedIon = TopReplacement->FixedIon;
     356      SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
     357      SecondOtherAtom->FixedIon = TopReplacement->FixedIon;
     358      ThirdOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity
     359      ThirdOtherAtom->FixedIon = TopReplacement->FixedIon;
     360      FirstOtherAtom->father = NULL;  //  we are just an added hydrogen with no father
     361      SecondOtherAtom->father = NULL;  //  we are just an added hydrogen with no father
     362      ThirdOtherAtom->father = NULL;  //  we are just an added hydrogen with no father
     363
     364      // we need to vectors orthonormal the InBondvector
     365      AllWentWell = AllWentWell && Orthovector1.GetOneNormalVector(&InBondvector);
     366//      *out << Verbose(3) << "Orthovector1: ";
     367//      Orthovector1.Output(out);
     368//      *out << endl;
     369      AllWentWell = AllWentWell && Orthovector2.MakeNormalVector(&InBondvector, &Orthovector1);
     370//      *out << Verbose(3) << "Orthovector2: ";
     371//      Orthovector2.Output(out);
     372//      *out << endl;
     373
     374      // create correct coordination for the three atoms
     375      alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.;  // retrieve triple bond angle from database
     376      l = BondRescale;        // desired bond length
     377      b = 2.*l*sin(alpha);    // base length of isosceles triangle
     378      d = l*sqrt(cos(alpha)*cos(alpha) - sin(alpha)*sin(alpha)/3.);  // length for InBondvector
     379      f = b/sqrt(3.);  // length for Orthvector1
     380      g = b/2.;        // length for Orthvector2
     381//      *out << Verbose(3) << "Bond length and half-angle: " << l << ", " << alpha << "\t (b,d,f,g) = " << b << ", " << d << ", " << f << ", " << g << ", " << endl;
     382//      *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;
     383      factors[0] = d;
     384      factors[1] = f;
     385      factors[2] = 0.;
     386      FirstOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);
     387      factors[1] = -0.5*f;
     388      factors[2] = g;
     389      SecondOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);
     390      factors[2] = -g;
     391      ThirdOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);
     392
     393      // rescale each to correct BondDistance
     394//      FirstOtherAtom->x.Scale(&BondRescale);
     395//      SecondOtherAtom->x.Scale(&BondRescale);
     396//      ThirdOtherAtom->x.Scale(&BondRescale);
     397
     398      // and relative to *origin atom
     399      FirstOtherAtom->x.AddVector(&TopOrigin->x);
     400      SecondOtherAtom->x.AddVector(&TopOrigin->x);
     401      ThirdOtherAtom->x.AddVector(&TopOrigin->x);
     402
     403      // ... and add to molecule
     404      AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);
     405      AllWentWell = AllWentWell && AddAtom(SecondOtherAtom);
     406      AllWentWell = AllWentWell && AddAtom(ThirdOtherAtom);
     407//      *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";
     408//      FirstOtherAtom->x.Output(out);
     409//      *out << endl;
     410//      *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: ";
     411//      SecondOtherAtom->x.Output(out);
     412//      *out << endl;
     413//      *out << Verbose(4) << "Added " << *ThirdOtherAtom << " at: ";
     414//      ThirdOtherAtom->x.Output(out);
     415//      *out << endl;
     416      Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);
     417      Binder->Cyclic = false;
     418      Binder->Type = TreeEdge;
     419      Binder = AddBond(BottomOrigin, SecondOtherAtom, 1);
     420      Binder->Cyclic = false;
     421      Binder->Type = TreeEdge;
     422      Binder = AddBond(BottomOrigin, ThirdOtherAtom, 1);
     423      Binder->Cyclic = false;
     424      Binder->Type = TreeEdge;
     425      break;
     426    default:
     427      cerr << "ERROR: BondDegree does not state single, double or triple bond!" << endl;
     428      AllWentWell = false;
     429      break;
     430  }
     431
     432//  *out << Verbose(3) << "End of AddHydrogenReplacementAtom." << endl;
     433  return AllWentWell;
    434434};
    435435
     
    441441bool molecule::AddXYZFile(string filename)
    442442{
    443         istringstream *input = NULL;
    444         int NumberOfAtoms = 0; // atom number in xyz read
    445         int i, j; // loop variables
    446         atom *Walker = NULL;    // pointer to added atom
    447         char shorthand[3];      // shorthand for atom name
    448         ifstream xyzfile;        // xyz file
    449         string line;            // currently parsed line
    450         double x[3];            // atom coordinates
    451 
    452         xyzfile.open(filename.c_str());
    453         if (!xyzfile)
    454                 return false;
    455 
    456         getline(xyzfile,line,'\n'); // Read numer of atoms in file
    457         input = new istringstream(line);
    458         *input >> NumberOfAtoms;
    459         cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl;
    460         getline(xyzfile,line,'\n'); // Read comment
    461         cout << Verbose(1) << "Comment: " << line << endl;
    462 
    463         if (MDSteps == 0) // no atoms yet present
    464                 MDSteps++;
    465         for(i=0;i<NumberOfAtoms;i++){
    466                 Walker = new atom;
    467                 getline(xyzfile,line,'\n');
    468                 istringstream *item = new istringstream(line);
    469                 //istringstream input(line);
    470                 //cout << Verbose(1) << "Reading: " << line << endl;
    471                 *item >> shorthand;
    472                 *item >> x[0];
    473                 *item >> x[1];
    474                 *item >> x[2];
    475                 Walker->type = elemente->FindElement(shorthand);
    476                 if (Walker->type == NULL) {
    477                         cerr << "Could not parse the element at line: '" << line << "', setting to H.";
    478                         Walker->type = elemente->FindElement(1);
    479                 }
    480                 if (Trajectories[Walker].R.size() <= (unsigned int)MDSteps) {
    481                         Trajectories[Walker].R.resize(MDSteps+10);
    482                         Trajectories[Walker].U.resize(MDSteps+10);
    483                         Trajectories[Walker].F.resize(MDSteps+10);
    484                 }
    485                 for(j=NDIM;j--;) {
    486                         Walker->x.x[j] = x[j];
    487                         Trajectories[Walker].R.at(MDSteps-1).x[j] = x[j];
    488                         Trajectories[Walker].U.at(MDSteps-1).x[j] = 0;
    489                         Trajectories[Walker].F.at(MDSteps-1).x[j] = 0;
    490                 }
    491                 AddAtom(Walker);        // add to molecule
    492                 delete(item);
    493         }
    494         xyzfile.close();
    495         delete(input);
    496         return true;
     443  istringstream *input = NULL;
     444  int NumberOfAtoms = 0; // atom number in xyz read
     445  int i, j; // loop variables
     446  atom *Walker = NULL;  // pointer to added atom
     447  char shorthand[3];  // shorthand for atom name
     448  ifstream xyzfile;  // xyz file
     449  string line;    // currently parsed line
     450  double x[3];    // atom coordinates
     451
     452  xyzfile.open(filename.c_str());
     453  if (!xyzfile)
     454    return false;
     455
     456  getline(xyzfile,line,'\n'); // Read numer of atoms in file
     457  input = new istringstream(line);
     458  *input >> NumberOfAtoms;
     459  cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl;
     460  getline(xyzfile,line,'\n'); // Read comment
     461  cout << Verbose(1) << "Comment: " << line << endl;
     462
     463  if (MDSteps == 0) // no atoms yet present
     464    MDSteps++;
     465  for(i=0;i<NumberOfAtoms;i++){
     466    Walker = new atom;
     467    getline(xyzfile,line,'\n');
     468    istringstream *item = new istringstream(line);
     469    //istringstream input(line);
     470    //cout << Verbose(1) << "Reading: " << line << endl;
     471    *item >> shorthand;
     472    *item >> x[0];
     473    *item >> x[1];
     474    *item >> x[2];
     475    Walker->type = elemente->FindElement(shorthand);
     476    if (Walker->type == NULL) {
     477      cerr << "Could not parse the element at line: '" << line << "', setting to H.";
     478      Walker->type = elemente->FindElement(1);
     479    }
     480    if (Trajectories[Walker].R.size() <= (unsigned int)MDSteps) {
     481      Trajectories[Walker].R.resize(MDSteps+10);
     482      Trajectories[Walker].U.resize(MDSteps+10);
     483      Trajectories[Walker].F.resize(MDSteps+10);
     484    }
     485    for(j=NDIM;j--;) {
     486      Walker->x.x[j] = x[j];
     487      Trajectories[Walker].R.at(MDSteps-1).x[j] = x[j];
     488      Trajectories[Walker].U.at(MDSteps-1).x[j] = 0;
     489      Trajectories[Walker].F.at(MDSteps-1).x[j] = 0;
     490    }
     491    AddAtom(Walker);  // add to molecule
     492    delete(item);
     493  }
     494  xyzfile.close();
     495  delete(input);
     496  return true;
    497497};
    498498
     
    502502molecule *molecule::CopyMolecule()
    503503{
    504         molecule *copy = new molecule(elemente);
    505         atom *CurrentAtom = NULL;
    506         atom *LeftAtom = NULL, *RightAtom = NULL;
    507         atom *Walker = NULL;
    508 
    509         // copy all atoms
    510         Walker = start;
    511         while(Walker->next != end) {
    512                 Walker = Walker->next;
    513                 CurrentAtom = copy->AddCopyAtom(Walker);
    514         }
    515 
    516         // copy all bonds
    517         bond *Binder = first;
    518         bond *NewBond = NULL;
    519         while(Binder->next != last) {
    520                 Binder = Binder->next;
    521                 // get the pendant atoms of current bond in the copy molecule
    522                 LeftAtom = copy->start;
    523                 while (LeftAtom->next != copy->end) {
    524                         LeftAtom = LeftAtom->next;
    525                         if (LeftAtom->father == Binder->leftatom)
    526                                 break;
    527                 }
    528                 RightAtom = copy->start;
    529                 while (RightAtom->next != copy->end) {
    530                         RightAtom = RightAtom->next;
    531                         if (RightAtom->father == Binder->rightatom)
    532                                 break;
    533                 }
    534                 NewBond = copy->AddBond(LeftAtom, RightAtom, Binder->BondDegree);
    535                 NewBond->Cyclic = Binder->Cyclic;
    536                 if (Binder->Cyclic)
    537                         copy->NoCyclicBonds++;
    538                 NewBond->Type = Binder->Type;
    539         }
    540         // correct fathers
    541         Walker = copy->start;
    542         while(Walker->next != copy->end) {
    543                 Walker = Walker->next;
    544                 if (Walker->father->father == Walker->father)    // same atom in copy's father points to itself
    545                         Walker->father = Walker;        // set father to itself (copy of a whole molecule)
    546                 else
    547                  Walker->father = Walker->father->father;       // set father to original's father
    548         }
    549         // copy values
    550         copy->CountAtoms((ofstream *)&cout);
    551         copy->CountElements();
    552         if (first->next != last) {      // if adjaceny list is present
    553                 copy->BondDistance = BondDistance;
    554                 copy->CreateListOfBondsPerAtom((ofstream *)&cout);
    555         }
    556 
    557         return copy;
     504  molecule *copy = new molecule(elemente);
     505  atom *CurrentAtom = NULL;
     506  atom *LeftAtom = NULL, *RightAtom = NULL;
     507  atom *Walker = NULL;
     508
     509  // copy all atoms
     510  Walker = start;
     511  while(Walker->next != end) {
     512    Walker = Walker->next;
     513    CurrentAtom = copy->AddCopyAtom(Walker);
     514  }
     515
     516  // copy all bonds
     517  bond *Binder = first;
     518  bond *NewBond = NULL;
     519  while(Binder->next != last) {
     520    Binder = Binder->next;
     521    // get the pendant atoms of current bond in the copy molecule
     522    LeftAtom = copy->start;
     523    while (LeftAtom->next != copy->end) {
     524      LeftAtom = LeftAtom->next;
     525      if (LeftAtom->father == Binder->leftatom)
     526        break;
     527    }
     528    RightAtom = copy->start;
     529    while (RightAtom->next != copy->end) {
     530      RightAtom = RightAtom->next;
     531      if (RightAtom->father == Binder->rightatom)
     532        break;
     533    }
     534    NewBond = copy->AddBond(LeftAtom, RightAtom, Binder->BondDegree);
     535    NewBond->Cyclic = Binder->Cyclic;
     536    if (Binder->Cyclic)
     537      copy->NoCyclicBonds++;
     538    NewBond->Type = Binder->Type;
     539  }
     540  // correct fathers
     541  Walker = copy->start;
     542  while(Walker->next != copy->end) {
     543    Walker = Walker->next;
     544    if (Walker->father->father == Walker->father)  // same atom in copy's father points to itself
     545      Walker->father = Walker;  // set father to itself (copy of a whole molecule)
     546    else
     547     Walker->father = Walker->father->father;  // set father to original's father
     548  }
     549  // copy values
     550  copy->CountAtoms((ofstream *)&cout);
     551  copy->CountElements();
     552  if (first->next != last) {  // if adjaceny list is present
     553    copy->BondDistance = BondDistance;
     554    copy->CreateListOfBondsPerAtom((ofstream *)&cout);
     555  }
     556
     557  return copy;
    558558};
    559559
     
    566566bond * molecule::AddBond(atom *atom1, atom *atom2, int degree=1)
    567567{
    568         bond *Binder = NULL;
    569         if ((atom1 != NULL) && (FindAtom(atom1->nr) != NULL) && (atom2 != NULL) && (FindAtom(atom2->nr) != NULL)) {
    570                 Binder = new bond(atom1, atom2, degree, BondCount++);
    571                 if ((atom1->type != NULL) && (atom1->type->Z != 1) && (atom2->type != NULL) && (atom2->type->Z != 1))
    572                         NoNonBonds++;
    573                 add(Binder, last);
    574         } else {
    575                 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;
    576         }
    577         return Binder;
     568  bond *Binder = NULL;
     569  if ((atom1 != NULL) && (FindAtom(atom1->nr) != NULL) && (atom2 != NULL) && (FindAtom(atom2->nr) != NULL)) {
     570    Binder = new bond(atom1, atom2, degree, BondCount++);
     571    if ((atom1->type != NULL) && (atom1->type->Z != 1) && (atom2->type != NULL) && (atom2->type->Z != 1))
     572      NoNonBonds++;
     573    add(Binder, last);
     574  } else {
     575    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;
     576  }
     577  return Binder;
    578578};
    579579
     
    585585bool molecule::RemoveBond(bond *pointer)
    586586{
    587         //cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl;
    588         removewithoutcheck(pointer);
    589         return true;
     587  //cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl;
     588  removewithoutcheck(pointer);
     589  return true;
    590590};
    591591
     
    597597bool molecule::RemoveBonds(atom *BondPartner)
    598598{
    599         cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl;
    600         return false;
     599  cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl;
     600  return false;
    601601};
    602602
     
    622622void molecule::SetBoxDimension(Vector *dim)
    623623{
    624         cell_size[0] = dim->x[0];
    625         cell_size[1] = 0.;
    626         cell_size[2] = dim->x[1];
    627         cell_size[3] = 0.;
    628         cell_size[4] = 0.;
    629         cell_size[5] = dim->x[2];
     624  cell_size[0] = dim->x[0];
     625  cell_size[1] = 0.;
     626  cell_size[2] = dim->x[1];
     627  cell_size[3] = 0.;
     628  cell_size[4] = 0.;
     629  cell_size[5] = dim->x[2];
    630630};
    631631
     
    636636bool molecule::CenterInBox(ofstream *out, Vector *BoxLengths)
    637637{
    638         bool status = true;
    639         atom *ptr = NULL;
    640         Vector *min = new Vector;
    641         Vector *max = new Vector;
    642 
    643         // gather min and max for each axis
    644         ptr = start->next;      // start at first in list
    645         if (ptr != end) {        //list not empty?
    646                 for (int i=NDIM;i--;) {
    647                         max->x[i] = ptr->x.x[i];
    648                         min->x[i] = ptr->x.x[i];
    649                 }
    650                 while (ptr->next != end) {      // continue with second if present
    651                         ptr = ptr->next;
    652                         //ptr->Output(1,1,out);
    653                         for (int i=NDIM;i--;) {
    654                                 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i];
    655                                 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i];
    656                         }
    657                 }
    658         }
    659         // sanity check
    660         for(int i=NDIM;i--;) {
    661                 if (max->x[i] - min->x[i] > BoxLengths->x[i])
    662                         status = false;
    663         }
    664         // warn if check failed
    665         if (!status)
    666                 *out << "WARNING: molecule is bigger than defined box!" << endl;
    667         else {  // else center in box
    668                 max->AddVector(min);
    669                 max->Scale(-1.);
    670                 max->AddVector(BoxLengths);
    671                 max->Scale(0.5);
     638  bool status = true;
     639  atom *ptr = NULL;
     640  Vector *min = new Vector;
     641  Vector *max = new Vector;
     642
     643  // gather min and max for each axis
     644  ptr = start->next;  // start at first in list
     645  if (ptr != end) {  //list not empty?
     646    for (int i=NDIM;i--;) {
     647      max->x[i] = ptr->x.x[i];
     648      min->x[i] = ptr->x.x[i];
     649    }
     650    while (ptr->next != end) {  // continue with second if present
     651      ptr = ptr->next;
     652      //ptr->Output(1,1,out);
     653      for (int i=NDIM;i--;) {
     654        max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i];
     655        min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i];
     656      }
     657    }
     658  }
     659  // sanity check
     660  for(int i=NDIM;i--;) {
     661    if (max->x[i] - min->x[i] > BoxLengths->x[i])
     662      status = false;
     663  }
     664  // warn if check failed
     665  if (!status)
     666    *out << "WARNING: molecule is bigger than defined box!" << endl;
     667  else {  // else center in box
     668    max->AddVector(min);
     669    max->Scale(-1.);
     670    max->AddVector(BoxLengths);
     671    max->Scale(0.5);
    672672    Translate(max);
    673673    Center.Zero();
    674         }
    675 
    676         // free and exit
    677         delete(min);
    678         delete(max);
    679         return status;
     674  }
     675
     676  // free and exit
     677  delete(min);
     678  delete(max);
     679  return status;
    680680};
    681681
     
    686686void molecule::CenterEdge(ofstream *out, Vector *max)
    687687{
    688         Vector *min = new Vector;
    689 
    690 //      *out << Verbose(3) << "Begin of CenterEdge." << endl;
    691         atom *ptr = start->next;        // start at first in list
    692         if (ptr != end) {        //list not empty?
    693                 for (int i=NDIM;i--;) {
    694                         max->x[i] = ptr->x.x[i];
    695                         min->x[i] = ptr->x.x[i];
    696                 }
    697                 while (ptr->next != end) {      // continue with second if present
    698                         ptr = ptr->next;
    699                         //ptr->Output(1,1,out);
    700                         for (int i=NDIM;i--;) {
    701                                 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i];
    702                                 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i];
    703                         }
    704                 }
    705 //              *out << Verbose(4) << "Maximum is ";
    706 //              max->Output(out);
    707 //              *out << ", Minimum is ";
    708 //              min->Output(out);
    709 //              *out << endl;
    710                 min->Scale(-1.);
    711                 max->AddVector(min);
    712                 Translate(min);
    713                 Center.Zero();
    714         }
    715         delete(min);
    716 //      *out << Verbose(3) << "End of CenterEdge." << endl;
     688  Vector *min = new Vector;
     689
     690//  *out << Verbose(3) << "Begin of CenterEdge." << endl;
     691  atom *ptr = start->next;  // start at first in list
     692  if (ptr != end) {  //list not empty?
     693    for (int i=NDIM;i--;) {
     694      max->x[i] = ptr->x.x[i];
     695      min->x[i] = ptr->x.x[i];
     696    }
     697    while (ptr->next != end) {  // continue with second if present
     698      ptr = ptr->next;
     699      //ptr->Output(1,1,out);
     700      for (int i=NDIM;i--;) {
     701        max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i];
     702        min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i];
     703      }
     704    }
     705//    *out << Verbose(4) << "Maximum is ";
     706//    max->Output(out);
     707//    *out << ", Minimum is ";
     708//    min->Output(out);
     709//    *out << endl;
     710    min->Scale(-1.);
     711    max->AddVector(min);
     712    Translate(min);
     713    Center.Zero();
     714  }
     715  delete(min);
     716//  *out << Verbose(3) << "End of CenterEdge." << endl;
    717717};
    718718
     
    723723void molecule::CenterOrigin(ofstream *out)
    724724{
    725         int Num = 0;
    726         atom *ptr = start->next;        // start at first in list
    727 
    728         Center.Zero();
    729 
    730         if (ptr != end) {        //list not empty?
    731                 while (ptr->next != end) {      // continue with second if present
    732                         ptr = ptr->next;
    733                         Num++;
    734                         Center.AddVector(&ptr->x);
    735                 }
    736                 Center.Scale(-1./Num); // divide through total number (and sign for direction)
    737           Translate(&Center);
    738           Center.Zero();
    739         }
     725  int Num = 0;
     726  atom *ptr = start->next;  // start at first in list
     727
     728  Center.Zero();
     729
     730  if (ptr != end) {  //list not empty?
     731    while (ptr->next != end) {  // continue with second if present
     732      ptr = ptr->next;
     733      Num++;
     734      Center.AddVector(&ptr->x);
     735    }
     736    Center.Scale(-1./Num); // divide through total number (and sign for direction)
     737    Translate(&Center);
     738    Center.Zero();
     739  }
    740740};
    741741
     
    746746Vector * molecule::DetermineCenterOfAll(ofstream *out)
    747747{
    748         atom *ptr = start->next;        // start at first in list
    749         Vector *a = new Vector();
    750         Vector tmp;
    751         double Num = 0;
    752 
    753         a->Zero();
    754 
    755         if (ptr != end) {        //list not empty?
    756                 while (ptr->next != end) {      // continue with second if present
    757                         ptr = ptr->next;
    758                         Num += 1.;
    759                         tmp.CopyVector(&ptr->x);
    760                         a->AddVector(&tmp);
    761                 }
    762                 a->Scale(-1./Num); // divide through total mass (and sign for direction)
    763         }
    764         //cout << Verbose(1) << "Resulting center of gravity: ";
    765         //a->Output(out);
    766         //cout << endl;
    767         return a;
     748  atom *ptr = start->next;  // start at first in list
     749  Vector *a = new Vector();
     750  Vector tmp;
     751  double Num = 0;
     752
     753  a->Zero();
     754
     755  if (ptr != end) {  //list not empty?
     756    while (ptr->next != end) {  // continue with second if present
     757      ptr = ptr->next;
     758      Num += 1.;
     759      tmp.CopyVector(&ptr->x);
     760      a->AddVector(&tmp);
     761    }
     762    a->Scale(-1./Num); // divide through total mass (and sign for direction)
     763  }
     764  //cout << Verbose(1) << "Resulting center of gravity: ";
     765  //a->Output(out);
     766  //cout << endl;
     767  return a;
    768768};
    769769
     
    774774Vector * molecule::DetermineCenterOfGravity(ofstream *out)
    775775{
    776         atom *ptr = start->next;        // start at first in list
    777         Vector *a = new Vector();
    778         Vector tmp;
    779         double Num = 0;
    780 
    781         a->Zero();
    782 
    783         if (ptr != end) {        //list not empty?
    784                 while (ptr->next != end) {      // continue with second if present
    785                         ptr = ptr->next;
    786                         Num += ptr->type->mass;
    787                         tmp.CopyVector(&ptr->x);
    788                         tmp.Scale(ptr->type->mass);     // scale by mass
    789                         a->AddVector(&tmp);
    790                 }
    791                 a->Scale(-1./Num); // divide through total mass (and sign for direction)
    792         }
    793 //      *out << Verbose(1) << "Resulting center of gravity: ";
    794 //      a->Output(out);
    795 //      *out << endl;
    796         return a;
     776  atom *ptr = start->next;  // start at first in list
     777  Vector *a = new Vector();
     778  Vector tmp;
     779  double Num = 0;
     780
     781  a->Zero();
     782
     783  if (ptr != end) {  //list not empty?
     784    while (ptr->next != end) {  // continue with second if present
     785      ptr = ptr->next;
     786      Num += ptr->type->mass;
     787      tmp.CopyVector(&ptr->x);
     788      tmp.Scale(ptr->type->mass);  // scale by mass
     789      a->AddVector(&tmp);
     790    }
     791    a->Scale(-1./Num); // divide through total mass (and sign for direction)
     792  }
     793//  *out << Verbose(1) << "Resulting center of gravity: ";
     794//  a->Output(out);
     795//  *out << endl;
     796  return a;
    797797};
    798798
     
    803803void molecule::CenterPeriodic(ofstream *out)
    804804{
    805         DeterminePeriodicCenter(Center);
     805  DeterminePeriodicCenter(Center);
    806806};
    807807
     
    820820void molecule::Scale(double **factor)
    821821{
    822         atom *ptr = start;
    823 
    824         while (ptr->next != end) {
    825                 ptr = ptr->next;
    826                 for (int j=0;j<MDSteps;j++)
    827                         Trajectories[ptr].R.at(j).Scale(factor);
    828                 ptr->x.Scale(factor);
    829         }
     822  atom *ptr = start;
     823
     824  while (ptr->next != end) {
     825    ptr = ptr->next;
     826    for (int j=0;j<MDSteps;j++)
     827      Trajectories[ptr].R.at(j).Scale(factor);
     828    ptr->x.Scale(factor);
     829  }
    830830};
    831831
     
    835835void molecule::Translate(const Vector *trans)
    836836{
    837         atom *ptr = start;
    838 
    839         while (ptr->next != end) {
    840                 ptr = ptr->next;
    841                 for (int j=0;j<MDSteps;j++)
    842                         Trajectories[ptr].R.at(j).Translate(trans);
    843                 ptr->x.Translate(trans);
    844         }
     837  atom *ptr = start;
     838
     839  while (ptr->next != end) {
     840    ptr = ptr->next;
     841    for (int j=0;j<MDSteps;j++)
     842      Trajectories[ptr].R.at(j).Translate(trans);
     843    ptr->x.Translate(trans);
     844  }
    845845};
    846846
     
    850850void molecule::Mirror(const Vector *n)
    851851{
    852         atom *ptr = start;
    853 
    854         while (ptr->next != end) {
    855                 ptr = ptr->next;
    856                 for (int j=0;j<MDSteps;j++)
    857                         Trajectories[ptr].R.at(j).Mirror(n);
    858                 ptr->x.Mirror(n);
    859         }
     852  atom *ptr = start;
     853
     854  while (ptr->next != end) {
     855    ptr = ptr->next;
     856    for (int j=0;j<MDSteps;j++)
     857      Trajectories[ptr].R.at(j).Mirror(n);
     858    ptr->x.Mirror(n);
     859  }
    860860};
    861861
     
    865865void molecule::DeterminePeriodicCenter(Vector &center)
    866866{
    867         atom *Walker = start;
    868         bond *Binder = NULL;
    869         double *matrix = ReturnFullMatrixforSymmetric(cell_size);
    870         double tmp;
    871         bool flag;
    872         Vector Testvector, Translationvector;
    873 
    874         do {
    875                 center.Zero();
    876                 flag = true;
    877                 while (Walker->next != end) {
    878                         Walker = Walker->next;
     867  atom *Walker = start;
     868  bond *Binder = NULL;
     869  double *matrix = ReturnFullMatrixforSymmetric(cell_size);
     870  double tmp;
     871  bool flag;
     872  Vector Testvector, Translationvector;
     873
     874  do {
     875    center.Zero();
     876    flag = true;
     877    while (Walker->next != end) {
     878      Walker = Walker->next;
    879879#ifdef ADDHYDROGEN
    880                         if (Walker->type->Z != 1) {
     880      if (Walker->type->Z != 1) {
    881881#endif
    882                                 Testvector.CopyVector(&Walker->x);
    883                                 Testvector.InverseMatrixMultiplication(matrix);
    884                                 Translationvector.Zero();
    885                                 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {
    886                                         Binder = ListOfBondsPerAtom[Walker->nr][i];
    887                                         if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing
    888                                                 for (int j=0;j<NDIM;j++) {
    889                                                         tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j];
    890                                                         if ((fabs(tmp)) > BondDistance) {
    891                                                                 flag = false;
    892                                                                 cout << Verbose(0) << "Hit: atom " << Walker->Name << " in bond " << *Binder << " has to be shifted due to " << tmp << "." << endl;
    893                                                                 if (tmp > 0)
    894                                                                         Translationvector.x[j] -= 1.;
    895                                                                 else
    896                                                                         Translationvector.x[j] += 1.;
    897                                                         }
    898                                                 }
    899                                 }
    900                                 Testvector.AddVector(&Translationvector);
    901                                 Testvector.MatrixMultiplication(matrix);
    902                                 center.AddVector(&Testvector);
    903                                 cout << Verbose(1) << "vector is: ";
    904                                 Testvector.Output((ofstream *)&cout);
    905                                 cout << endl;
     882        Testvector.CopyVector(&Walker->x);
     883        Testvector.InverseMatrixMultiplication(matrix);
     884        Translationvector.Zero();
     885        for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {
     886          Binder = ListOfBondsPerAtom[Walker->nr][i];
     887          if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing
     888            for (int j=0;j<NDIM;j++) {
     889              tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j];
     890              if ((fabs(tmp)) > BondDistance) {
     891                flag = false;
     892                cout << Verbose(0) << "Hit: atom " << Walker->Name << " in bond " << *Binder << " has to be shifted due to " << tmp << "." << endl;
     893                if (tmp > 0)
     894                  Translationvector.x[j] -= 1.;
     895                else
     896                  Translationvector.x[j] += 1.;
     897              }
     898            }
     899        }
     900        Testvector.AddVector(&Translationvector);
     901        Testvector.MatrixMultiplication(matrix);
     902        center.AddVector(&Testvector);
     903        cout << Verbose(1) << "vector is: ";
     904        Testvector.Output((ofstream *)&cout);
     905        cout << endl;
    906906#ifdef ADDHYDROGEN
    907                                 // now also change all hydrogens
    908                                 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {
    909                                         Binder = ListOfBondsPerAtom[Walker->nr][i];
    910                                         if (Binder->GetOtherAtom(Walker)->type->Z == 1) {
    911                                                 Testvector.CopyVector(&Binder->GetOtherAtom(Walker)->x);
    912                                                 Testvector.InverseMatrixMultiplication(matrix);
    913                                                 Testvector.AddVector(&Translationvector);
    914                                                 Testvector.MatrixMultiplication(matrix);
    915                                                 center.AddVector(&Testvector);
    916                                                 cout << Verbose(1) << "Hydrogen vector is: ";
    917                                                 Testvector.Output((ofstream *)&cout);
    918                                                 cout << endl;
    919                                         }
    920                                 }
    921                         }
     907        // now also change all hydrogens
     908        for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {
     909          Binder = ListOfBondsPerAtom[Walker->nr][i];
     910          if (Binder->GetOtherAtom(Walker)->type->Z == 1) {
     911            Testvector.CopyVector(&Binder->GetOtherAtom(Walker)->x);
     912            Testvector.InverseMatrixMultiplication(matrix);
     913            Testvector.AddVector(&Translationvector);
     914            Testvector.MatrixMultiplication(matrix);
     915            center.AddVector(&Testvector);
     916            cout << Verbose(1) << "Hydrogen vector is: ";
     917            Testvector.Output((ofstream *)&cout);
     918            cout << endl;
     919          }
     920        }
     921      }
    922922#endif
    923                 }
    924         } while (!flag);
    925         Free((void **)&matrix, "molecule::DetermineCenter: *matrix");
    926         center.Scale(1./(double)AtomCount);
     923    }
     924  } while (!flag);
     925  Free((void **)&matrix, "molecule::DetermineCenter: *matrix");
     926  center.Scale(1./(double)AtomCount);
    927927};
    928928
     
    933933void molecule::PrincipalAxisSystem(ofstream *out, bool DoRotate)
    934934{
    935         atom *ptr = start;      // start at first in list
    936         double InertiaTensor[NDIM*NDIM];
    937         Vector *CenterOfGravity = DetermineCenterOfGravity(out);
    938 
    939         CenterAtVector(out, CenterOfGravity);
    940 
    941         // reset inertia tensor
    942         for(int i=0;i<NDIM*NDIM;i++)
    943                 InertiaTensor[i] = 0.;
    944 
    945         // sum up inertia tensor
    946         while (ptr->next != end) {
    947                 ptr = ptr->next;
    948                 Vector x;
    949                 x.CopyVector(&ptr->x);
    950                 //x.SubtractVector(CenterOfGravity);
    951                 InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]);
    952                 InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]);
    953                 InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]);
    954                 InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]);
    955                 InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]);
    956                 InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]);
    957                 InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]);
    958                 InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]);
    959                 InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]);
    960         }
    961         // print InertiaTensor for debugging
    962         *out << "The inertia tensor is:" << endl;
    963         for(int i=0;i<NDIM;i++) {
    964                 for(int j=0;j<NDIM;j++)
    965                         *out << InertiaTensor[i*NDIM+j] << " ";
    966                 *out << endl;
    967         }
    968         *out << endl;
    969 
    970         // diagonalize to determine principal axis system
    971         gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(NDIM);
    972         gsl_matrix_view m = gsl_matrix_view_array(InertiaTensor, NDIM, NDIM);
    973         gsl_vector *eval = gsl_vector_alloc(NDIM);
    974         gsl_matrix *evec = gsl_matrix_alloc(NDIM, NDIM);
    975         gsl_eigen_symmv(&m.matrix, eval, evec, T);
    976         gsl_eigen_symmv_free(T);
    977         gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC);
    978 
    979         for(int i=0;i<NDIM;i++) {
    980                 *out << Verbose(1) << "eigenvalue = " << gsl_vector_get(eval, i);
    981                 *out << ", eigenvector = (" << evec->data[i * evec->tda + 0] << "," << evec->data[i * evec->tda + 1] << "," << evec->data[i * evec->tda + 2] << ")" << endl;
    982         }
    983 
    984         // check whether we rotate or not
    985         if (DoRotate) {
    986                 *out << Verbose(1) << "Transforming molecule into PAS ... ";
    987                 // the eigenvectors specify the transformation matrix
    988                 ptr = start;
    989                 while (ptr->next != end) {
    990                         ptr = ptr->next;
    991                         for (int j=0;j<MDSteps;j++)
    992                                 Trajectories[ptr].R.at(j).MatrixMultiplication(evec->data);
    993                         ptr->x.MatrixMultiplication(evec->data);
    994                 }
    995                 *out << "done." << endl;
    996 
    997                 // summing anew for debugging (resulting matrix has to be diagonal!)
    998                 // reset inertia tensor
    999                 for(int i=0;i<NDIM*NDIM;i++)
    1000                         InertiaTensor[i] = 0.;
    1001 
    1002                 // sum up inertia tensor
    1003                 ptr = start;
    1004                 while (ptr->next != end) {
    1005                         ptr = ptr->next;
    1006                         Vector x;
    1007                         x.CopyVector(&ptr->x);
    1008                         //x.SubtractVector(CenterOfGravity);
    1009                         InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]);
    1010                         InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]);
    1011                         InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]);
    1012                         InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]);
    1013                         InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]);
    1014                         InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]);
    1015                         InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]);
    1016                         InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]);
    1017                         InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]);
    1018                 }
    1019                 // print InertiaTensor for debugging
    1020                 *out << "The inertia tensor is:" << endl;
    1021                 for(int i=0;i<NDIM;i++) {
    1022                         for(int j=0;j<NDIM;j++)
    1023                                 *out << InertiaTensor[i*NDIM+j] << " ";
    1024                         *out << endl;
    1025                 }
    1026                 *out << endl;
    1027         }
    1028 
    1029         // free everything
    1030         delete(CenterOfGravity);
    1031         gsl_vector_free(eval);
    1032         gsl_matrix_free(evec);
     935  atom *ptr = start;  // start at first in list
     936  double InertiaTensor[NDIM*NDIM];
     937  Vector *CenterOfGravity = DetermineCenterOfGravity(out);
     938
     939  CenterAtVector(out, CenterOfGravity);
     940
     941  // reset inertia tensor
     942  for(int i=0;i<NDIM*NDIM;i++)
     943    InertiaTensor[i] = 0.;
     944
     945  // sum up inertia tensor
     946  while (ptr->next != end) {
     947    ptr = ptr->next;
     948    Vector x;
     949    x.CopyVector(&ptr->x);
     950    //x.SubtractVector(CenterOfGravity);
     951    InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]);
     952    InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]);
     953    InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]);
     954    InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]);
     955    InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]);
     956    InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]);
     957    InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]);
     958    InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]);
     959    InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]);
     960  }
     961  // print InertiaTensor for debugging
     962  *out << "The inertia tensor is:" << endl;
     963  for(int i=0;i<NDIM;i++) {
     964    for(int j=0;j<NDIM;j++)
     965      *out << InertiaTensor[i*NDIM+j] << " ";
     966    *out << endl;
     967  }
     968  *out << endl;
     969
     970  // diagonalize to determine principal axis system
     971  gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(NDIM);
     972  gsl_matrix_view m = gsl_matrix_view_array(InertiaTensor, NDIM, NDIM);
     973  gsl_vector *eval = gsl_vector_alloc(NDIM);
     974  gsl_matrix *evec = gsl_matrix_alloc(NDIM, NDIM);
     975  gsl_eigen_symmv(&m.matrix, eval, evec, T);
     976  gsl_eigen_symmv_free(T);
     977  gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC);
     978
     979  for(int i=0;i<NDIM;i++) {
     980    *out << Verbose(1) << "eigenvalue = " << gsl_vector_get(eval, i);
     981    *out << ", eigenvector = (" << evec->data[i * evec->tda + 0] << "," << evec->data[i * evec->tda + 1] << "," << evec->data[i * evec->tda + 2] << ")" << endl;
     982  }
     983
     984  // check whether we rotate or not
     985  if (DoRotate) {
     986    *out << Verbose(1) << "Transforming molecule into PAS ... ";
     987    // the eigenvectors specify the transformation matrix
     988    ptr = start;
     989    while (ptr->next != end) {
     990      ptr = ptr->next;
     991      for (int j=0;j<MDSteps;j++)
     992        Trajectories[ptr].R.at(j).MatrixMultiplication(evec->data);
     993      ptr->x.MatrixMultiplication(evec->data);
     994    }
     995    *out << "done." << endl;
     996
     997    // summing anew for debugging (resulting matrix has to be diagonal!)
     998    // reset inertia tensor
     999    for(int i=0;i<NDIM*NDIM;i++)
     1000      InertiaTensor[i] = 0.;
     1001
     1002    // sum up inertia tensor
     1003    ptr = start;
     1004    while (ptr->next != end) {
     1005      ptr = ptr->next;
     1006      Vector x;
     1007      x.CopyVector(&ptr->x);
     1008      //x.SubtractVector(CenterOfGravity);
     1009      InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]);
     1010      InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]);
     1011      InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]);
     1012      InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]);
     1013      InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]);
     1014      InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]);
     1015      InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]);
     1016      InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]);
     1017      InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]);
     1018    }
     1019    // print InertiaTensor for debugging
     1020    *out << "The inertia tensor is:" << endl;
     1021    for(int i=0;i<NDIM;i++) {
     1022      for(int j=0;j<NDIM;j++)
     1023        *out << InertiaTensor[i*NDIM+j] << " ";
     1024      *out << endl;
     1025    }
     1026    *out << endl;
     1027  }
     1028
     1029  // free everything
     1030  delete(CenterOfGravity);
     1031  gsl_vector_free(eval);
     1032  gsl_matrix_free(evec);
    10331033};
    10341034
     
    10441044bool molecule::VerletForceIntegration(char *file, double delta_t, bool IsAngstroem)
    10451045{
    1046         element *runner = elemente->start;
    1047         atom *walker = NULL;
    1048         int AtomNo;
    1049         ifstream input(file);
    1050         string token;
    1051         stringstream item;
    1052         double a, IonMass;
    1053         ForceMatrix Force;
    1054         Vector tmpvector;
    1055 
    1056         CountElements();        // make sure ElementsInMolecule is up to date
    1057 
    1058         // check file
    1059         if (input == NULL) {
    1060                 return false;
    1061         } else {
    1062                 // parse file into ForceMatrix
    1063                 if (!Force.ParseMatrix(file, 0,0,0)) {
    1064                         cerr << "Could not parse Force Matrix file " << file << "." << endl;
    1065                         return false;
    1066                 }
    1067                 if (Force.RowCounter[0] != AtomCount) {
    1068                         cerr << "Mismatch between number of atoms in file " << Force.RowCounter[0] << " and in molecule " << AtomCount << "." << endl;
    1069                         return false;
    1070                 }
    1071                 // correct Forces
    1072 //              for(int d=0;d<NDIM;d++)
    1073 //                      tmpvector.x[d] = 0.;
    1074 //              for(int i=0;i<AtomCount;i++)
    1075 //                      for(int d=0;d<NDIM;d++) {
    1076 //                              tmpvector.x[d] += Force.Matrix[0][i][d+5];
    1077 //                      }
    1078 //              for(int i=0;i<AtomCount;i++)
    1079 //                      for(int d=0;d<NDIM;d++) {
    1080 //                              Force.Matrix[0][i][d+5] -= tmpvector.x[d]/(double)AtomCount;
    1081 //                      }
    1082                 // and perform Verlet integration for each atom with position, velocity and force vector
    1083                 runner = elemente->start;
    1084                 while (runner->next != elemente->end) { // go through every element
    1085                         runner = runner->next;
    1086                         IonMass = runner->mass;
    1087                         a = delta_t*0.5/IonMass;                                // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a
    1088                         if (ElementsInMolecule[runner->Z]) { // if this element got atoms
    1089                                 AtomNo = 0;
    1090                                 walker = start;
    1091                                 while (walker->next != end) { // go through every atom of this element
    1092                                         walker = walker->next;
    1093                                         if (walker->type == runner) { // if this atom fits to element
    1094                                                 // check size of vectors
    1095                                                 if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) {
    1096                                                         //cout << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl;
    1097                                                         Trajectories[walker].R.resize(MDSteps+10);
    1098                                                         Trajectories[walker].U.resize(MDSteps+10);
    1099                                                         Trajectories[walker].F.resize(MDSteps+10);
    1100                                                 }
    1101                                                 // 1. calculate x(t+\delta t)
    1102                                                 for (int d=0; d<NDIM; d++) {
    1103                                                         Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5];
    1104                                                         Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d];
    1105                                                         Trajectories[walker].R.at(MDSteps).x[d] += delta_t*(Trajectories[walker].U.at(MDSteps-1).x[d]);
    1106                                                         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
    1107                                                 }
    1108                                                 // 2. Calculate v(t+\delta t)
    1109                                                 for (int d=0; d<NDIM; d++) {
    1110                                                         Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d];
    1111                                                         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;
    1112                                                 }
    1113 //                                              cout << "Integrated position&velocity of step " << (MDSteps) << ": (";
    1114 //                                              for (int d=0;d<NDIM;d++)
    1115 //                                                      cout << Trajectories[walker].R.at(MDSteps).x[d] << " ";                                 // next step
    1116 //                                              cout << ")\t(";
    1117 //                                              for (int d=0;d<NDIM;d++)
    1118 //                                                      cout << Trajectories[walker].U.at(MDSteps).x[d] << " ";                                 // next step
    1119 //                                              cout << ")" << endl;
    1120                                                 // next atom
    1121                                                 AtomNo++;
    1122                                         }
    1123                                 }
    1124                         }
    1125                 }
    1126         }
    1127 //      // correct velocities (rather momenta) so that center of mass remains motionless
    1128 //      tmpvector.zero()
    1129 //      IonMass = 0.;
    1130 //      walker = start;
    1131 //      while (walker->next != end) { // go through every atom
    1132 //              walker = walker->next;
    1133 //              IonMass += walker->type->mass;  // sum up total mass
    1134 //              for(int d=0;d<NDIM;d++) {
    1135 //                      tmpvector.x[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass;
    1136 //              }
    1137 //      }
    1138 //      walker = start;
    1139 //      while (walker->next != end) { // go through every atom of this element
    1140 //              walker = walker->next;
    1141 //              for(int d=0;d<NDIM;d++) {
    1142 //                      Trajectories[walker].U.at(MDSteps).x[d] -= tmpvector.x[d]*walker->type->mass/IonMass;
    1143 //              }
    1144 //      }
    1145         MDSteps++;
    1146 
    1147 
    1148         // exit
    1149         return true;
     1046  element *runner = elemente->start;
     1047  atom *walker = NULL;
     1048  int AtomNo;
     1049  ifstream input(file);
     1050  string token;
     1051  stringstream item;
     1052  double a, IonMass;
     1053  ForceMatrix Force;
     1054  Vector tmpvector;
     1055
     1056  CountElements();  // make sure ElementsInMolecule is up to date
     1057
     1058  // check file
     1059  if (input == NULL) {
     1060    return false;
     1061  } else {
     1062    // parse file into ForceMatrix
     1063    if (!Force.ParseMatrix(file, 0,0,0)) {
     1064      cerr << "Could not parse Force Matrix file " << file << "." << endl;
     1065      return false;
     1066    }
     1067    if (Force.RowCounter[0] != AtomCount) {
     1068      cerr << "Mismatch between number of atoms in file " << Force.RowCounter[0] << " and in molecule " << AtomCount << "." << endl;
     1069      return false;
     1070    }
     1071    // correct Forces
     1072//    for(int d=0;d<NDIM;d++)
     1073//      tmpvector.x[d] = 0.;
     1074//    for(int i=0;i<AtomCount;i++)
     1075//      for(int d=0;d<NDIM;d++) {
     1076//        tmpvector.x[d] += Force.Matrix[0][i][d+5];
     1077//      }
     1078//    for(int i=0;i<AtomCount;i++)
     1079//      for(int d=0;d<NDIM;d++) {
     1080//        Force.Matrix[0][i][d+5] -= tmpvector.x[d]/(double)AtomCount;
     1081//      }
     1082    // and perform Verlet integration for each atom with position, velocity and force vector
     1083    runner = elemente->start;
     1084    while (runner->next != elemente->end) { // go through every element
     1085      runner = runner->next;
     1086      IonMass = runner->mass;
     1087      a = delta_t*0.5/IonMass;        // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a
     1088      if (ElementsInMolecule[runner->Z]) { // if this element got atoms
     1089        AtomNo = 0;
     1090        walker = start;
     1091        while (walker->next != end) { // go through every atom of this element
     1092          walker = walker->next;
     1093          if (walker->type == runner) { // if this atom fits to element
     1094            // check size of vectors
     1095            if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) {
     1096              //cout << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl;
     1097              Trajectories[walker].R.resize(MDSteps+10);
     1098              Trajectories[walker].U.resize(MDSteps+10);
     1099              Trajectories[walker].F.resize(MDSteps+10);
     1100            }
     1101            // 1. calculate x(t+\delta t)
     1102            for (int d=0; d<NDIM; d++) {
     1103              Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5];
     1104              Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d];
     1105              Trajectories[walker].R.at(MDSteps).x[d] += delta_t*(Trajectories[walker].U.at(MDSteps-1).x[d]);
     1106              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
     1107            }
     1108            // 2. Calculate v(t+\delta t)
     1109            for (int d=0; d<NDIM; d++) {
     1110              Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d];
     1111              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;
     1112            }
     1113//            cout << "Integrated position&velocity of step " << (MDSteps) << ": (";
     1114//            for (int d=0;d<NDIM;d++)
     1115//              cout << Trajectories[walker].R.at(MDSteps).x[d] << " ";          // next step
     1116//            cout << ")\t(";
     1117//            for (int d=0;d<NDIM;d++)
     1118//              cout << Trajectories[walker].U.at(MDSteps).x[d] << " ";          // next step
     1119//            cout << ")" << endl;
     1120            // next atom
     1121            AtomNo++;
     1122          }
     1123        }
     1124      }
     1125    }
     1126  }
     1127//  // correct velocities (rather momenta) so that center of mass remains motionless
     1128//  tmpvector.zero()
     1129//  IonMass = 0.;
     1130//  walker = start;
     1131//  while (walker->next != end) { // go through every atom
     1132//    walker = walker->next;
     1133//    IonMass += walker->type->mass;  // sum up total mass
     1134//    for(int d=0;d<NDIM;d++) {
     1135//      tmpvector.x[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass;
     1136//    }
     1137//  }
     1138//  walker = start;
     1139//  while (walker->next != end) { // go through every atom of this element
     1140//    walker = walker->next;
     1141//    for(int d=0;d<NDIM;d++) {
     1142//      Trajectories[walker].U.at(MDSteps).x[d] -= tmpvector.x[d]*walker->type->mass/IonMass;
     1143//    }
     1144//  }
     1145  MDSteps++;
     1146
     1147
     1148  // exit
     1149  return true;
    11501150};
    11511151
     
    11551155void molecule::Align(Vector *n)
    11561156{
    1157         atom *ptr = start;
    1158         double alpha, tmp;
    1159         Vector z_axis;
    1160         z_axis.x[0] = 0.;
    1161         z_axis.x[1] = 0.;
    1162         z_axis.x[2] = 1.;
    1163 
    1164         // rotate on z-x plane
    1165         cout << Verbose(0) << "Begin of Aligning all atoms." << endl;
    1166         alpha = atan(-n->x[0]/n->x[2]);
    1167         cout << Verbose(1) << "Z-X-angle: " << alpha << " ... ";
    1168         while (ptr->next != end) {
    1169                 ptr = ptr->next;
    1170                 tmp = ptr->x.x[0];
    1171                 ptr->x.x[0] =   cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];
    1172                 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];
    1173                 for (int j=0;j<MDSteps;j++) {
    1174                         tmp = Trajectories[ptr].R.at(j).x[0];
    1175                         Trajectories[ptr].R.at(j).x[0] =        cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];
    1176                         Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2];
    1177                 }
    1178         }
    1179         // rotate n vector
    1180         tmp = n->x[0];
    1181         n->x[0] =       cos(alpha) * tmp +      sin(alpha) * n->x[2];
    1182         n->x[2] = -sin(alpha) * tmp +   cos(alpha) * n->x[2];
    1183         cout << Verbose(1) << "alignment vector after first rotation: ";
    1184         n->Output((ofstream *)&cout);
    1185         cout << endl;
    1186 
    1187         // rotate on z-y plane
    1188         ptr = start;
    1189         alpha = atan(-n->x[1]/n->x[2]);
    1190         cout << Verbose(1) << "Z-Y-angle: " << alpha << " ... ";
    1191         while (ptr->next != end) {
    1192                 ptr = ptr->next;
    1193                 tmp = ptr->x.x[1];
    1194                 ptr->x.x[1] =   cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];
    1195                 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];
    1196                 for (int j=0;j<MDSteps;j++) {
    1197                         tmp = Trajectories[ptr].R.at(j).x[1];
    1198                         Trajectories[ptr].R.at(j).x[1] =        cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];
    1199                         Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2];
    1200                 }
    1201         }
    1202         // rotate n vector (for consistency check)
    1203         tmp = n->x[1];
    1204         n->x[1] =       cos(alpha) * tmp +      sin(alpha) * n->x[2];
    1205         n->x[2] = -sin(alpha) * tmp +   cos(alpha) * n->x[2];
    1206 
    1207         cout << Verbose(1) << "alignment vector after second rotation: ";
    1208         n->Output((ofstream *)&cout);
    1209         cout << Verbose(1) << endl;
    1210         cout << Verbose(0) << "End of Aligning all atoms." << endl;
     1157  atom *ptr = start;
     1158  double alpha, tmp;
     1159  Vector z_axis;
     1160  z_axis.x[0] = 0.;
     1161  z_axis.x[1] = 0.;
     1162  z_axis.x[2] = 1.;
     1163
     1164  // rotate on z-x plane
     1165  cout << Verbose(0) << "Begin of Aligning all atoms." << endl;
     1166  alpha = atan(-n->x[0]/n->x[2]);
     1167  cout << Verbose(1) << "Z-X-angle: " << alpha << " ... ";
     1168  while (ptr->next != end) {
     1169    ptr = ptr->next;
     1170    tmp = ptr->x.x[0];
     1171    ptr->x.x[0] =  cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];
     1172    ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];
     1173    for (int j=0;j<MDSteps;j++) {
     1174      tmp = Trajectories[ptr].R.at(j).x[0];
     1175      Trajectories[ptr].R.at(j).x[0] =  cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];
     1176      Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2];
     1177    }
     1178  }
     1179  // rotate n vector
     1180  tmp = n->x[0];
     1181  n->x[0] =  cos(alpha) * tmp +  sin(alpha) * n->x[2];
     1182  n->x[2] = -sin(alpha) * tmp +  cos(alpha) * n->x[2];
     1183  cout << Verbose(1) << "alignment vector after first rotation: ";
     1184  n->Output((ofstream *)&cout);
     1185  cout << endl;
     1186
     1187  // rotate on z-y plane
     1188  ptr = start;
     1189  alpha = atan(-n->x[1]/n->x[2]);
     1190  cout << Verbose(1) << "Z-Y-angle: " << alpha << " ... ";
     1191  while (ptr->next != end) {
     1192    ptr = ptr->next;
     1193    tmp = ptr->x.x[1];
     1194    ptr->x.x[1] =  cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];
     1195    ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];
     1196    for (int j=0;j<MDSteps;j++) {
     1197      tmp = Trajectories[ptr].R.at(j).x[1];
     1198      Trajectories[ptr].R.at(j).x[1] =  cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];
     1199      Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2];
     1200    }
     1201  }
     1202  // rotate n vector (for consistency check)
     1203  tmp = n->x[1];
     1204  n->x[1] =  cos(alpha) * tmp +  sin(alpha) * n->x[2];
     1205  n->x[2] = -sin(alpha) * tmp +  cos(alpha) * n->x[2];
     1206
     1207  cout << Verbose(1) << "alignment vector after second rotation: ";
     1208  n->Output((ofstream *)&cout);
     1209  cout << Verbose(1) << endl;
     1210  cout << Verbose(0) << "End of Aligning all atoms." << endl;
    12111211};
    12121212
     
    12171217bool molecule::RemoveAtom(atom *pointer)
    12181218{
    1219         if (ElementsInMolecule[pointer->type->Z] != 0)  // this would indicate an error
    1220                 ElementsInMolecule[pointer->type->Z]--; // decrease number of atom of this element
    1221         else
    1222                 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl;
    1223         if (ElementsInMolecule[pointer->type->Z] == 0)  // was last atom of this element?
    1224                 ElementCount--;
    1225         Trajectories.erase(pointer);
    1226         return remove(pointer, start, end);
     1219  if (ElementsInMolecule[pointer->type->Z] != 0)  // this would indicate an error
     1220    ElementsInMolecule[pointer->type->Z]--;  // decrease number of atom of this element
     1221  else
     1222    cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl;
     1223  if (ElementsInMolecule[pointer->type->Z] == 0)  // was last atom of this element?
     1224    ElementCount--;
     1225  Trajectories.erase(pointer);
     1226  return remove(pointer, start, end);
    12271227};
    12281228
     
    12511251bool molecule::CleanupMolecule()
    12521252{
    1253         return (cleanup(start,end) && cleanup(first,last));
     1253  return (cleanup(start,end) && cleanup(first,last));
    12541254};
    12551255
     
    12581258 * \return pointer to atom or NULL
    12591259 */
    1260 atom * molecule::FindAtom(int Nr)       const{
    1261         atom * walker = find(&Nr, start,end);
    1262         if (walker != NULL) {
    1263                 //cout << Verbose(0) << "Found Atom Nr. " << walker->nr << endl;
    1264                 return walker;
    1265         } else {
    1266                 cout << Verbose(0) << "Atom not found in list." << endl;
    1267                 return NULL;
    1268         }
     1260atom * molecule::FindAtom(int Nr)  const{
     1261  atom * walker = find(&Nr, start,end);
     1262  if (walker != NULL) {
     1263    //cout << Verbose(0) << "Found Atom Nr. " << walker->nr << endl;
     1264    return walker;
     1265  } else {
     1266    cout << Verbose(0) << "Atom not found in list." << endl;
     1267    return NULL;
     1268  }
    12691269};
    12701270
     
    12741274atom * molecule::AskAtom(string text)
    12751275{
    1276         int No;
    1277         atom *ion = NULL;
    1278         do {
    1279                 //cout << Verbose(0) << "============Atom list==========================" << endl;
    1280                 //mol->Output((ofstream *)&cout);
    1281                 //cout << Verbose(0) << "===============================================" << endl;
    1282                 cout << Verbose(0) << text;
    1283                 cin >> No;
    1284                 ion = this->FindAtom(No);
    1285         } while (ion == NULL);
    1286         return ion;
     1276  int No;
     1277  atom *ion = NULL;
     1278  do {
     1279    //cout << Verbose(0) << "============Atom list==========================" << endl;
     1280    //mol->Output((ofstream *)&cout);
     1281    //cout << Verbose(0) << "===============================================" << endl;
     1282    cout << Verbose(0) << text;
     1283    cin >> No;
     1284    ion = this->FindAtom(No);
     1285  } while (ion == NULL);
     1286  return ion;
    12871287};
    12881288
     
    12931293bool molecule::CheckBounds(const Vector *x) const
    12941294{
    1295         bool result = true;
    1296         int j =-1;
    1297         for (int i=0;i<NDIM;i++) {
    1298                 j += i+1;
    1299                 result = result && ((x->x[i] >= 0) && (x->x[i] < cell_size[j]));
    1300         }
    1301         //return result;
    1302         return true; /// probably not gonna use the check no more
     1295  bool result = true;
     1296  int j =-1;
     1297  for (int i=0;i<NDIM;i++) {
     1298    j += i+1;
     1299    result = result && ((x->x[i] >= 0) && (x->x[i] < cell_size[j]));
     1300  }
     1301  //return result;
     1302  return true; /// probably not gonna use the check no more
    13031303};
    13041304
     
    13101310double LeastSquareDistance (const gsl_vector * x, void * params)
    13111311{
    1312         double res = 0, t;
    1313         Vector a,b,c,d;
    1314         struct lsq_params *par = (struct lsq_params *)params;
    1315         atom *ptr = par->mol->start;
    1316 
    1317         // initialize vectors
    1318         a.x[0] = gsl_vector_get(x,0);
    1319         a.x[1] = gsl_vector_get(x,1);
    1320         a.x[2] = gsl_vector_get(x,2);
    1321         b.x[0] = gsl_vector_get(x,3);
    1322         b.x[1] = gsl_vector_get(x,4);
    1323         b.x[2] = gsl_vector_get(x,5);
    1324         // go through all atoms
    1325         while (ptr != par->mol->end) {
    1326                 ptr = ptr->next;
    1327                 if (ptr->type == ((struct lsq_params *)params)->type) { // for specific type
    1328                         c.CopyVector(&ptr->x);  // copy vector to temporary one
    1329                         c.SubtractVector(&a);    // subtract offset vector
    1330                         t = c.ScalarProduct(&b);                                        // get direction parameter
    1331                         d.CopyVector(&b);                        // and create vector
    1332                         d.Scale(&t);
    1333                         c.SubtractVector(&d);    // ... yielding distance vector
    1334                         res += d.ScalarProduct((const Vector *)&d);                             // add squared distance
    1335                 }
    1336         }
    1337         return res;
     1312  double res = 0, t;
     1313  Vector a,b,c,d;
     1314  struct lsq_params *par = (struct lsq_params *)params;
     1315  atom *ptr = par->mol->start;
     1316
     1317  // initialize vectors
     1318  a.x[0] = gsl_vector_get(x,0);
     1319  a.x[1] = gsl_vector_get(x,1);
     1320  a.x[2] = gsl_vector_get(x,2);
     1321  b.x[0] = gsl_vector_get(x,3);
     1322  b.x[1] = gsl_vector_get(x,4);
     1323  b.x[2] = gsl_vector_get(x,5);
     1324  // go through all atoms
     1325  while (ptr != par->mol->end) {
     1326    ptr = ptr->next;
     1327    if (ptr->type == ((struct lsq_params *)params)->type) { // for specific type
     1328      c.CopyVector(&ptr->x);  // copy vector to temporary one
     1329      c.SubtractVector(&a);  // subtract offset vector
     1330      t = c.ScalarProduct(&b);          // get direction parameter
     1331      d.CopyVector(&b);      // and create vector
     1332      d.Scale(&t);
     1333      c.SubtractVector(&d);  // ... yielding distance vector
     1334      res += d.ScalarProduct((const Vector *)&d);        // add squared distance
     1335    }
     1336  }
     1337  return res;
    13381338};
    13391339
     
    13431343void molecule::GetAlignvector(struct lsq_params * par) const
    13441344{
    1345                 int np = 6;
    1346 
    1347         const gsl_multimin_fminimizer_type *T =
    1348                 gsl_multimin_fminimizer_nmsimplex;
    1349         gsl_multimin_fminimizer *s = NULL;
    1350         gsl_vector *ss;
    1351         gsl_multimin_function minex_func;
    1352 
    1353         size_t iter = 0, i;
    1354         int status;
    1355         double size;
    1356 
    1357         /* Initial vertex size vector */
    1358         ss = gsl_vector_alloc (np);
    1359 
    1360         /* Set all step sizes to 1 */
    1361         gsl_vector_set_all (ss, 1.0);
    1362 
    1363         /* Starting point */
    1364         par->x = gsl_vector_alloc (np);
    1365         par->mol = this;
    1366 
    1367          gsl_vector_set (par->x, 0, 0.0);       // offset
    1368         gsl_vector_set (par->x, 1, 0.0);
    1369         gsl_vector_set (par->x, 2, 0.0);
    1370          gsl_vector_set (par->x, 3, 0.0);       // direction
    1371         gsl_vector_set (par->x, 4, 0.0);
    1372         gsl_vector_set (par->x, 5, 1.0);
    1373 
    1374         /* Initialize method and iterate */
    1375         minex_func.f = &LeastSquareDistance;
    1376         minex_func.n = np;
    1377         minex_func.params = (void *)par;
    1378 
    1379         s = gsl_multimin_fminimizer_alloc (T, np);
    1380         gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss);
    1381 
    1382         do
    1383                 {
    1384                         iter++;
    1385                         status = gsl_multimin_fminimizer_iterate(s);
    1386 
    1387                         if (status)
    1388                                 break;
    1389 
    1390                         size = gsl_multimin_fminimizer_size (s);
    1391                         status = gsl_multimin_test_size (size, 1e-2);
    1392 
    1393                         if (status == GSL_SUCCESS)
    1394                                 {
    1395                                         printf ("converged to minimum at\n");
    1396                                 }
    1397 
    1398                         printf ("%5d ", (int)iter);
    1399                         for (i = 0; i < (size_t)np; i++)
    1400                                 {
    1401                                         printf ("%10.3e ", gsl_vector_get (s->x, i));
    1402                                 }
    1403                         printf ("f() = %7.3f size = %.3f\n", s->fval, size);
    1404                 }
    1405         while (status == GSL_CONTINUE && iter < 100);
    1406 
    1407         for (i=0;i<(size_t)np;i++)
    1408                 gsl_vector_set(par->x, i, gsl_vector_get(s->x, i));
    1409         //gsl_vector_free(par->x);
    1410         gsl_vector_free(ss);
    1411         gsl_multimin_fminimizer_free (s);
     1345    int np = 6;
     1346
     1347  const gsl_multimin_fminimizer_type *T =
     1348    gsl_multimin_fminimizer_nmsimplex;
     1349  gsl_multimin_fminimizer *s = NULL;
     1350  gsl_vector *ss;
     1351  gsl_multimin_function minex_func;
     1352
     1353  size_t iter = 0, i;
     1354  int status;
     1355  double size;
     1356
     1357  /* Initial vertex size vector */
     1358  ss = gsl_vector_alloc (np);
     1359
     1360  /* Set all step sizes to 1 */
     1361  gsl_vector_set_all (ss, 1.0);
     1362
     1363  /* Starting point */
     1364  par->x = gsl_vector_alloc (np);
     1365  par->mol = this;
     1366
     1367   gsl_vector_set (par->x, 0, 0.0);  // offset
     1368  gsl_vector_set (par->x, 1, 0.0);
     1369  gsl_vector_set (par->x, 2, 0.0);
     1370   gsl_vector_set (par->x, 3, 0.0);  // direction
     1371  gsl_vector_set (par->x, 4, 0.0);
     1372  gsl_vector_set (par->x, 5, 1.0);
     1373
     1374  /* Initialize method and iterate */
     1375  minex_func.f = &LeastSquareDistance;
     1376  minex_func.n = np;
     1377  minex_func.params = (void *)par;
     1378
     1379  s = gsl_multimin_fminimizer_alloc (T, np);
     1380  gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss);
     1381
     1382  do
     1383    {
     1384      iter++;
     1385      status = gsl_multimin_fminimizer_iterate(s);
     1386
     1387      if (status)
     1388        break;
     1389
     1390      size = gsl_multimin_fminimizer_size (s);
     1391      status = gsl_multimin_test_size (size, 1e-2);
     1392
     1393      if (status == GSL_SUCCESS)
     1394        {
     1395          printf ("converged to minimum at\n");
     1396        }
     1397
     1398      printf ("%5d ", (int)iter);
     1399      for (i = 0; i < (size_t)np; i++)
     1400        {
     1401          printf ("%10.3e ", gsl_vector_get (s->x, i));
     1402        }
     1403      printf ("f() = %7.3f size = %.3f\n", s->fval, size);
     1404    }
     1405  while (status == GSL_CONTINUE && iter < 100);
     1406
     1407  for (i=0;i<(size_t)np;i++)
     1408    gsl_vector_set(par->x, i, gsl_vector_get(s->x, i));
     1409  //gsl_vector_free(par->x);
     1410  gsl_vector_free(ss);
     1411  gsl_multimin_fminimizer_free (s);
    14121412};
    14131413
     
    14171417bool molecule::Output(ofstream *out)
    14181418{
    1419         element *runner;
    1420         atom *walker = NULL;
    1421         int ElementNo, AtomNo;
    1422         CountElements();
    1423 
    1424         if (out == NULL) {
    1425                 return false;
    1426         } else {
    1427                 *out << "#Ion_TypeNr._Nr.R[0]           R[1]            R[2]            MoveType (0 MoveIon, 1 FixedIon)" << endl;
    1428                 ElementNo = 0;
    1429                 runner = elemente->start;
    1430                 while (runner->next != elemente->end) { // go through every element
    1431                         runner = runner->next;
    1432                         if (ElementsInMolecule[runner->Z]) { // if this element got atoms
    1433                                 ElementNo++;
    1434                                 AtomNo = 0;
    1435                                 walker = start;
    1436                                 while (walker->next != end) { // go through every atom of this element
    1437                                         walker = walker->next;
    1438                                         if (walker->type == runner) { // if this atom fits to element
    1439                                                 AtomNo++;
    1440                                                 walker->Output(ElementNo, AtomNo, out); // removed due to trajectories
    1441                                         }
    1442                                 }
    1443                         }
    1444                 }
    1445                 return true;
    1446         }
     1419  element *runner;
     1420  atom *walker = NULL;
     1421  int ElementNo, AtomNo;
     1422  CountElements();
     1423
     1424  if (out == NULL) {
     1425    return false;
     1426  } else {
     1427    *out << "#Ion_TypeNr._Nr.R[0]    R[1]    R[2]    MoveType (0 MoveIon, 1 FixedIon)" << endl;
     1428    ElementNo = 0;
     1429    runner = elemente->start;
     1430    while (runner->next != elemente->end) { // go through every element
     1431      runner = runner->next;
     1432      if (ElementsInMolecule[runner->Z]) { // if this element got atoms
     1433        ElementNo++;
     1434        AtomNo = 0;
     1435        walker = start;
     1436        while (walker->next != end) { // go through every atom of this element
     1437          walker = walker->next;
     1438          if (walker->type == runner) { // if this atom fits to element
     1439            AtomNo++;
     1440            walker->Output(ElementNo, AtomNo, out); // removed due to trajectories
     1441          }
     1442        }
     1443      }
     1444    }
     1445    return true;
     1446  }
    14471447};
    14481448
     
    14521452bool molecule::OutputTrajectories(ofstream *out)
    14531453{
    1454         element *runner = NULL;
    1455         atom *walker = NULL;
    1456         int ElementNo, AtomNo;
    1457         CountElements();
    1458 
    1459         if (out == NULL) {
    1460                 return false;
    1461         } else {
    1462                 for (int step = 0; step < MDSteps; step++) {
    1463                         if (step == 0) {
    1464                                 *out << "#Ion_TypeNr._Nr.R[0]           R[1]            R[2]            MoveType (0 MoveIon, 1 FixedIon)" << endl;
    1465                         } else {
    1466                                 *out << "# ====== MD step " << step << " =========" << endl;
    1467                         }
    1468                         ElementNo = 0;
    1469                         runner = elemente->start;
    1470                         while (runner->next != elemente->end) { // go through every element
    1471                                 runner = runner->next;
    1472                                 if (ElementsInMolecule[runner->Z]) { // if this element got atoms
    1473                                         ElementNo++;
    1474                                         AtomNo = 0;
    1475                                         walker = start;
    1476                                         while (walker->next != end) { // go through every atom of this element
    1477                                                 walker = walker->next;
    1478                                                 if (walker->type == runner) { // if this atom fits to element
    1479                                                         AtomNo++;
    1480                                                         *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t"        << fixed << setprecision(9) << showpoint;
    1481                                                         *out << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2];
    1482                                                         *out << "\t" << walker->FixedIon;
    1483                                                         if (Trajectories[walker].U.at(step).Norm() > MYEPSILON)
    1484                                                                 *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";
    1485                                                         if (Trajectories[walker].F.at(step).Norm() > MYEPSILON)
    1486                                                                 *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";
    1487                                                         *out << "\t# Number in molecule " << walker->nr << endl;
    1488                                                 }
    1489                                         }
    1490                                 }
    1491                         }
    1492                 }
    1493                 return true;
    1494         }
     1454  element *runner = NULL;
     1455  atom *walker = NULL;
     1456  int ElementNo, AtomNo;
     1457  CountElements();
     1458
     1459  if (out == NULL) {
     1460    return false;
     1461  } else {
     1462    for (int step = 0; step < MDSteps; step++) {
     1463      if (step == 0) {
     1464        *out << "#Ion_TypeNr._Nr.R[0]    R[1]    R[2]    MoveType (0 MoveIon, 1 FixedIon)" << endl;
     1465      } else {
     1466        *out << "# ====== MD step " << step << " =========" << endl;
     1467      }
     1468      ElementNo = 0;
     1469      runner = elemente->start;
     1470      while (runner->next != elemente->end) { // go through every element
     1471        runner = runner->next;
     1472        if (ElementsInMolecule[runner->Z]) { // if this element got atoms
     1473          ElementNo++;
     1474          AtomNo = 0;
     1475          walker = start;
     1476          while (walker->next != end) { // go through every atom of this element
     1477            walker = walker->next;
     1478            if (walker->type == runner) { // if this atom fits to element
     1479              AtomNo++;
     1480              *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t"  << fixed << setprecision(9) << showpoint;
     1481              *out << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2];
     1482              *out << "\t" << walker->FixedIon;
     1483              if (Trajectories[walker].U.at(step).Norm() > MYEPSILON)
     1484                *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";
     1485              if (Trajectories[walker].F.at(step).Norm() > MYEPSILON)
     1486                *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";
     1487              *out << "\t# Number in molecule " << walker->nr << endl;
     1488            }
     1489          }
     1490        }
     1491      }
     1492    }
     1493    return true;
     1494  }
    14951495};
    14961496
     
    15001500void molecule::OutputListOfBonds(ofstream *out) const
    15011501{
    1502         *out << Verbose(2) << endl << "From Contents of ListOfBondsPerAtom, all non-hydrogen atoms:" << endl;
    1503         atom *Walker = start;
    1504         while (Walker->next != end) {
    1505                 Walker = Walker->next;
     1502  *out << Verbose(2) << endl << "From Contents of ListOfBondsPerAtom, all non-hydrogen atoms:" << endl;
     1503  atom *Walker = start;
     1504  while (Walker->next != end) {
     1505    Walker = Walker->next;
    15061506#ifdef ADDHYDROGEN
    1507                 if (Walker->type->Z != 1) {      // regard only non-hydrogen
     1507    if (Walker->type->Z != 1) {  // regard only non-hydrogen
    15081508#endif
    1509                         *out << Verbose(2) << "Atom " << Walker->Name << " has Bonds: "<<endl;
    1510                         for(int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) {
    1511                                 *out << Verbose(3) << *(ListOfBondsPerAtom)[Walker->nr][j] << endl;
    1512                         }
     1509      *out << Verbose(2) << "Atom " << Walker->Name << " has Bonds: "<<endl;
     1510      for(int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) {
     1511        *out << Verbose(3) << *(ListOfBondsPerAtom)[Walker->nr][j] << endl;
     1512      }
    15131513#ifdef ADDHYDROGEN
    1514                 }
     1514    }
    15151515#endif
    1516         }
    1517         *out << endl;
     1516  }
     1517  *out << endl;
    15181518};
    15191519
     
    15211521 * \param *out stream pointer
    15221522 */
    1523 bool molecule::Checkout(ofstream *out)  const
    1524 {
    1525         return elemente->Checkout(out, ElementsInMolecule);
     1523bool molecule::Checkout(ofstream *out)  const
     1524{
     1525  return elemente->Checkout(out, ElementsInMolecule);
    15261526};
    15271527
     
    15311531bool molecule::OutputTrajectoriesXYZ(ofstream *out)
    15321532{
    1533         atom *walker = NULL;
    1534         int No = 0;
    1535         time_t now;
    1536 
    1537         now = time((time_t *)NULL);      // Get the system time and put it into 'now' as 'calender time'
    1538         walker = start;
    1539         while (walker->next != end) { // go through every atom and count
    1540                 walker = walker->next;
    1541                 No++;
    1542         }
    1543         if (out != NULL) {
    1544                 for (int step=0;step<MDSteps;step++) {
    1545                         *out << No << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now);
    1546                         walker = start;
    1547                         while (walker->next != end) { // go through every atom of this element
    1548                                 walker = walker->next;
    1549                                 *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;
    1550                         }
    1551                 }
    1552                 return true;
    1553         } else
    1554                 return false;
     1533  atom *walker = NULL;
     1534  int No = 0;
     1535  time_t now;
     1536
     1537  now = time((time_t *)NULL);  // Get the system time and put it into 'now' as 'calender time'
     1538  walker = start;
     1539  while (walker->next != end) { // go through every atom and count
     1540    walker = walker->next;
     1541    No++;
     1542  }
     1543  if (out != NULL) {
     1544    for (int step=0;step<MDSteps;step++) {
     1545      *out << No << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now);
     1546      walker = start;
     1547      while (walker->next != end) { // go through every atom of this element
     1548        walker = walker->next;
     1549        *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;
     1550      }
     1551    }
     1552    return true;
     1553  } else
     1554    return false;
    15551555};
    15561556
     
    15601560bool molecule::OutputXYZ(ofstream *out) const
    15611561{
    1562         atom *walker = NULL;
    1563         int AtomNo = 0, ElementNo;
    1564         time_t now;
    1565         element *runner = NULL;
    1566 
    1567         now = time((time_t *)NULL);      // Get the system time and put it into 'now' as 'calender time'
    1568         walker = start;
    1569         while (walker->next != end) { // go through every atom and count
    1570                 walker = walker->next;
    1571                 AtomNo++;
    1572         }
    1573         if (out != NULL) {
    1574                 *out << AtomNo << "\n\tCreated by molecuilder on " << ctime(&now);
    1575                 ElementNo = 0;
    1576                 runner = elemente->start;
    1577                 while (runner->next != elemente->end) { // go through every element
    1578                         runner = runner->next;
    1579                         if (ElementsInMolecule[runner->Z]) { // if this element got atoms
    1580                                 ElementNo++;
    1581                                 walker = start;
    1582                                 while (walker->next != end) { // go through every atom of this element
    1583                                         walker = walker->next;
    1584                                         if (walker->type == runner) { // if this atom fits to element
    1585                                                 walker->OutputXYZLine(out);
    1586                                         }
    1587                                 }
    1588                         }
    1589                 }
    1590                 return true;
    1591         } else
    1592                 return false;
     1562  atom *walker = NULL;
     1563  int AtomNo = 0, ElementNo;
     1564  time_t now;
     1565  element *runner = NULL;
     1566
     1567  now = time((time_t *)NULL);  // Get the system time and put it into 'now' as 'calender time'
     1568  walker = start;
     1569  while (walker->next != end) { // go through every atom and count
     1570    walker = walker->next;
     1571    AtomNo++;
     1572  }
     1573  if (out != NULL) {
     1574    *out << AtomNo << "\n\tCreated by molecuilder on " << ctime(&now);
     1575    ElementNo = 0;
     1576    runner = elemente->start;
     1577    while (runner->next != elemente->end) { // go through every element
     1578      runner = runner->next;
     1579      if (ElementsInMolecule[runner->Z]) { // if this element got atoms
     1580        ElementNo++;
     1581        walker = start;
     1582        while (walker->next != end) { // go through every atom of this element
     1583          walker = walker->next;
     1584          if (walker->type == runner) { // if this atom fits to element
     1585            walker->OutputXYZLine(out);
     1586          }
     1587        }
     1588      }
     1589    }
     1590    return true;
     1591  } else
     1592    return false;
    15931593};
    15941594
     
    15981598void molecule::CountAtoms(ofstream *out)
    15991599{
    1600         int i = 0;
    1601         atom *Walker = start;
    1602         while (Walker->next != end) {
    1603                 Walker = Walker->next;
    1604                 i++;
    1605         }
    1606         if ((AtomCount == 0) || (i != AtomCount)) {
    1607                 *out << Verbose(3) << "Mismatch in AtomCount " << AtomCount << " and recounted number " << i << ", renaming all." << endl;
    1608                 AtomCount = i;
    1609 
    1610                 // count NonHydrogen atoms and give each atom a unique name
    1611                 if (AtomCount != 0) {
    1612                         i=0;
    1613                         NoNonHydrogen = 0;
    1614                         Walker = start;
    1615                         while (Walker->next != end) {
    1616                                 Walker = Walker->next;
    1617                                 Walker->nr = i; // update number in molecule (for easier referencing in FragmentMolecule lateron)
    1618                                 if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it
    1619                                         NoNonHydrogen++;
    1620                                 Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name");
    1621                                 Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name");
    1622                                 sprintf(Walker->Name, "%2s%02d", Walker->type->symbol, Walker->nr+1);
    1623                                 *out << "Naming atom nr. " << Walker->nr << " " << Walker->Name << "." << endl;
    1624                                 i++;
    1625                         }
    1626                 } else
    1627                         *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl;
    1628         }
     1600  int i = 0;
     1601  atom *Walker = start;
     1602  while (Walker->next != end) {
     1603    Walker = Walker->next;
     1604    i++;
     1605  }
     1606  if ((AtomCount == 0) || (i != AtomCount)) {
     1607    *out << Verbose(3) << "Mismatch in AtomCount " << AtomCount << " and recounted number " << i << ", renaming all." << endl;
     1608    AtomCount = i;
     1609
     1610    // count NonHydrogen atoms and give each atom a unique name
     1611    if (AtomCount != 0) {
     1612      i=0;
     1613      NoNonHydrogen = 0;
     1614      Walker = start;
     1615      while (Walker->next != end) {
     1616        Walker = Walker->next;
     1617        Walker->nr = i;  // update number in molecule (for easier referencing in FragmentMolecule lateron)
     1618        if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it
     1619          NoNonHydrogen++;
     1620        Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name");
     1621        Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name");
     1622        sprintf(Walker->Name, "%2s%02d", Walker->type->symbol, Walker->nr+1);
     1623        *out << "Naming atom nr. " << Walker->nr << " " << Walker->Name << "." << endl;
     1624        i++;
     1625      }
     1626    } else
     1627      *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl;
     1628  }
    16291629};
    16301630
     
    16331633void molecule::CountElements()
    16341634{
    1635         int i = 0;
    1636         for(i=MAX_ELEMENTS;i--;)
    1637                 ElementsInMolecule[i] = 0;
    1638         ElementCount = 0;
    1639 
    1640         atom *walker = start;
    1641         while (walker->next != end) {
    1642                 walker = walker->next;
    1643                 ElementsInMolecule[walker->type->Z]++;
    1644                 i++;
    1645         }
    1646         for(i=MAX_ELEMENTS;i--;)
    1647                 ElementCount += (ElementsInMolecule[i] != 0 ? 1 : 0);
     1635  int i = 0;
     1636  for(i=MAX_ELEMENTS;i--;)
     1637    ElementsInMolecule[i] = 0;
     1638  ElementCount = 0;
     1639
     1640  atom *walker = start;
     1641  while (walker->next != end) {
     1642    walker = walker->next;
     1643    ElementsInMolecule[walker->type->Z]++;
     1644    i++;
     1645  }
     1646  for(i=MAX_ELEMENTS;i--;)
     1647    ElementCount += (ElementsInMolecule[i] != 0 ? 1 : 0);
    16481648};
    16491649
     
    16551655int molecule::CountCyclicBonds(ofstream *out)
    16561656{
    1657         int No = 0;
    1658         int *MinimumRingSize = NULL;
    1659         MoleculeLeafClass *Subgraphs = NULL;
    1660         class StackClass<bond *> *BackEdgeStack = NULL;
    1661         bond *Binder = first;
    1662         if ((Binder->next != last) && (Binder->next->Type == Undetermined)) {
    1663                 *out << Verbose(0) << "No Depth-First-Search analysis performed so far, calling ..." << endl;
    1664                 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack);
    1665                 while (Subgraphs->next != NULL) {
    1666                         Subgraphs = Subgraphs->next;
    1667                         delete(Subgraphs->previous);
    1668                 }
    1669                 delete(Subgraphs);
    1670                 delete[](MinimumRingSize);
    1671         }
    1672         while(Binder->next != last) {
    1673                 Binder = Binder->next;
    1674                 if (Binder->Cyclic)
    1675                         No++;
    1676         }
    1677         delete(BackEdgeStack);
    1678         return No;
     1657  int No = 0;
     1658  int *MinimumRingSize = NULL;
     1659  MoleculeLeafClass *Subgraphs = NULL;
     1660  class StackClass<bond *> *BackEdgeStack = NULL;
     1661  bond *Binder = first;
     1662  if ((Binder->next != last) && (Binder->next->Type == Undetermined)) {
     1663    *out << Verbose(0) << "No Depth-First-Search analysis performed so far, calling ..." << endl;
     1664    Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack);
     1665    while (Subgraphs->next != NULL) {
     1666      Subgraphs = Subgraphs->next;
     1667      delete(Subgraphs->previous);
     1668    }
     1669    delete(Subgraphs);
     1670    delete[](MinimumRingSize);
     1671  }
     1672  while(Binder->next != last) {
     1673    Binder = Binder->next;
     1674    if (Binder->Cyclic)
     1675      No++;
     1676  }
     1677  delete(BackEdgeStack);
     1678  return No;
    16791679};
    16801680/** Returns Shading as a char string.
     
    16841684string molecule::GetColor(enum Shading color)
    16851685{
    1686         switch(color) {
    1687                 case white:
    1688                         return "white";
    1689                         break;
    1690                 case lightgray:
    1691                         return "lightgray";
    1692                         break;
    1693                 case darkgray:
    1694                         return "darkgray";
    1695                         break;
    1696                 case black:
    1697                         return "black";
    1698                         break;
    1699                 default:
    1700                         return "uncolored";
    1701                         break;
    1702         };
     1686  switch(color) {
     1687    case white:
     1688      return "white";
     1689      break;
     1690    case lightgray:
     1691      return "lightgray";
     1692      break;
     1693    case darkgray:
     1694      return "darkgray";
     1695      break;
     1696    case black:
     1697      return "black";
     1698      break;
     1699    default:
     1700      return "uncolored";
     1701      break;
     1702  };
    17031703};
    17041704
     
    17091709void molecule::CalculateOrbitals(class config &configuration)
    17101710{
    1711         configuration.MaxPsiDouble = configuration.PsiMaxNoDown = configuration.PsiMaxNoUp = configuration.PsiType = 0;
    1712         for(int i=MAX_ELEMENTS;i--;) {
    1713                 if (ElementsInMolecule[i] != 0) {
    1714                         //cout << "CalculateOrbitals: " << elemente->FindElement(i)->name << " has a valence of " << (int)elemente->FindElement(i)->Valence << " and there are " << ElementsInMolecule[i] << " of it." << endl;
    1715                         configuration.MaxPsiDouble += ElementsInMolecule[i]*((int)elemente->FindElement(i)->Valence);
    1716                 }
    1717         }
    1718         configuration.PsiMaxNoDown = configuration.MaxPsiDouble/2 + (configuration.MaxPsiDouble % 2);
    1719         configuration.PsiMaxNoUp = configuration.MaxPsiDouble/2;
    1720         configuration.MaxPsiDouble /= 2;
    1721         configuration.PsiType = (configuration.PsiMaxNoDown == configuration.PsiMaxNoUp) ? 0 : 1;
    1722         if ((configuration.PsiType == 1) && (configuration.ProcPEPsi < 2)) {
    1723                 configuration.ProcPEGamma /= 2;
    1724                 configuration.ProcPEPsi *= 2;
    1725         } else {
    1726                 configuration.ProcPEGamma *= configuration.ProcPEPsi;
    1727                 configuration.ProcPEPsi = 1;
    1728         }
    1729         configuration.InitMaxMinStopStep = configuration.MaxMinStopStep = configuration.MaxPsiDouble;
     1711  configuration.MaxPsiDouble = configuration.PsiMaxNoDown = configuration.PsiMaxNoUp = configuration.PsiType = 0;
     1712  for(int i=MAX_ELEMENTS;i--;) {
     1713    if (ElementsInMolecule[i] != 0) {
     1714      //cout << "CalculateOrbitals: " << elemente->FindElement(i)->name << " has a valence of " << (int)elemente->FindElement(i)->Valence << " and there are " << ElementsInMolecule[i] << " of it." << endl;
     1715      configuration.MaxPsiDouble += ElementsInMolecule[i]*((int)elemente->FindElement(i)->Valence);
     1716    }
     1717  }
     1718  configuration.PsiMaxNoDown = configuration.MaxPsiDouble/2 + (configuration.MaxPsiDouble % 2);
     1719  configuration.PsiMaxNoUp = configuration.MaxPsiDouble/2;
     1720  configuration.MaxPsiDouble /= 2;
     1721  configuration.PsiType = (configuration.PsiMaxNoDown == configuration.PsiMaxNoUp) ? 0 : 1;
     1722  if ((configuration.PsiType == 1) && (configuration.ProcPEPsi < 2)) {
     1723    configuration.ProcPEGamma /= 2;
     1724    configuration.ProcPEPsi *= 2;
     1725  } else {
     1726    configuration.ProcPEGamma *= configuration.ProcPEPsi;
     1727    configuration.ProcPEPsi = 1;
     1728  }
     1729  configuration.InitMaxMinStopStep = configuration.MaxMinStopStep = configuration.MaxPsiDouble;
    17301730};
    17311731
     
    17361736{
    17371737
    1738         // 1 We will parse bonds out of the dbond file created by tremolo.
    1739                         int atom1, atom2, temp;
    1740                         atom *Walker, *OtherWalker;
    1741 
    1742                                         if (!input)
    1743                                         {
    1744                                                 cout << Verbose(1) << "Opening silica failed \n";
    1745                                         };
    1746 
    1747                         *input >> ws >> atom1;
    1748                         *input >> ws >> atom2;
    1749                                         cout << Verbose(1) << "Scanning file\n";
    1750                                         while (!input->eof()) // Check whether we read everything already
    1751                                         {
    1752                                 *input >> ws >> atom1;
    1753                                 *input >> ws >> atom2;
    1754                                                 if(atom2<atom1) //Sort indices of atoms in order
    1755                                                 {
    1756                                                         temp=atom1;
    1757                                                         atom1=atom2;
    1758                                                         atom2=temp;
    1759                                                 };
    1760 
    1761                                                 Walker=start;
    1762                                                 while(Walker-> nr != atom1) // Find atom corresponding to first index
    1763                                                 {
    1764                                                         Walker = Walker->next;
    1765                                                 };
    1766                                                 OtherWalker = Walker->next;
    1767                                                 while(OtherWalker->nr != atom2) // Find atom corresponding to second index
    1768                                                 {
    1769                                                         OtherWalker= OtherWalker->next;
    1770                                                 };
    1771                                                 AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices.
    1772 
    1773                                         }
    1774 
    1775                                         CreateListOfBondsPerAtom(out);
     1738  // 1 We will parse bonds out of the dbond file created by tremolo.
     1739      int atom1, atom2, temp;
     1740      atom *Walker, *OtherWalker;
     1741
     1742          if (!input)
     1743          {
     1744            cout << Verbose(1) << "Opening silica failed \n";
     1745          };
     1746
     1747      *input >> ws >> atom1;
     1748      *input >> ws >> atom2;
     1749          cout << Verbose(1) << "Scanning file\n";
     1750          while (!input->eof()) // Check whether we read everything already
     1751          {
     1752        *input >> ws >> atom1;
     1753        *input >> ws >> atom2;
     1754            if(atom2<atom1) //Sort indices of atoms in order
     1755            {
     1756              temp=atom1;
     1757              atom1=atom2;
     1758              atom2=temp;
     1759            };
     1760
     1761            Walker=start;
     1762            while(Walker-> nr != atom1) // Find atom corresponding to first index
     1763            {
     1764              Walker = Walker->next;
     1765            };
     1766            OtherWalker = Walker->next;
     1767            while(OtherWalker->nr != atom2) // Find atom corresponding to second index
     1768            {
     1769              OtherWalker= OtherWalker->next;
     1770            };
     1771            AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices.
     1772
     1773          }
     1774
     1775          CreateListOfBondsPerAtom(out);
    17761776
    17771777};
     
    17841784 * To make it O(N log N) the function uses the linked-cell technique as follows:
    17851785 * The procedure is step-wise:
    1786  *      -# Remove every bond in list
    1787  *      -# Count the atoms in the molecule with CountAtoms()
    1788  *      -# partition cell into smaller linked cells of size \a bonddistance
    1789  *      -# put each atom into its corresponding cell
    1790  *      -# go through every cell, check the atoms therein against all possible bond partners in the 27 adjacent cells, add bond if true
    1791  *      -# create the list of bonds via CreateListOfBondsPerAtom()
    1792  *      -# correct the bond degree iteratively (single->double->triple bond)
    1793  *      -# finally print the bond list to \a *out if desired
     1786 *  -# Remove every bond in list
     1787 *  -# Count the atoms in the molecule with CountAtoms()
     1788 *  -# partition cell into smaller linked cells of size \a bonddistance
     1789 *  -# put each atom into its corresponding cell
     1790 *  -# go through every cell, check the atoms therein against all possible bond partners in the 27 adjacent cells, add bond if true
     1791 *  -# create the list of bonds via CreateListOfBondsPerAtom()
     1792 *  -# correct the bond degree iteratively (single->double->triple bond)
     1793 *  -# finally print the bond list to \a *out if desired
    17941794 * \param *out out stream for printing the matrix, NULL if no output
    17951795 * \param bonddistance length of linked cells (i.e. maximum minimal length checked)
     
    17991799{
    18001800
    1801         atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL;
    1802         int No, NoBonds, CandidateBondNo;
    1803         int NumberCells, divisor[NDIM], n[NDIM], N[NDIM], index, Index, j;
    1804         molecule **CellList;
    1805         double distance, MinDistance, MaxDistance;
    1806         double *matrix = ReturnFullMatrixforSymmetric(cell_size);
    1807         Vector x;
    1808         int FalseBondDegree = 0;
    1809 
    1810         BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem);
    1811         *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl;
    1812         // remove every bond from the list
    1813         if ((first->next != last) && (last->previous != first)) {       // there are bonds present
    1814                 cleanup(first,last);
    1815         }
    1816 
    1817         // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering)
    1818         CountAtoms(out);
    1819         *out << Verbose(1) << "AtomCount " << AtomCount << "." << endl;
    1820 
    1821         if (AtomCount != 0) {
    1822                 // 1. find divisor for each axis, such that a sphere with radius of at least bonddistance can be placed into each cell
    1823                 j=-1;
    1824                 for (int i=0;i<NDIM;i++) {
    1825                         j += i+1;
    1826                         divisor[i] = (int)floor(cell_size[j]/bonddistance); // take smaller value such that size of linked cell is at least bonddistance
    1827                         //*out << Verbose(1) << "divisor[" << i << "]   = " << divisor[i] << "." << endl;
    1828                 }
    1829                 // 2a. allocate memory for the cell list
    1830                 NumberCells = divisor[0]*divisor[1]*divisor[2];
    1831                 *out << Verbose(1) << "Allocating " << NumberCells << " cells." << endl;
    1832                 CellList = (molecule **) Malloc(sizeof(molecule *)*NumberCells, "molecule::CreateAdjacencyList - ** CellList");
    1833                 for (int i=NumberCells;i--;)
    1834                         CellList[i] = NULL;
    1835 
    1836                 // 2b. put all atoms into its corresponding list
    1837                 Walker = start;
    1838                 while(Walker->next != end) {
    1839                         Walker = Walker->next;
    1840                         //*out << Verbose(1) << "Current atom is " << *Walker << " with coordinates ";
    1841                         //Walker->x.Output(out);
    1842                         //*out << "." << endl;
    1843                         // compute the cell by the atom's coordinates
    1844                         j=-1;
    1845                         for (int i=0;i<NDIM;i++) {
    1846                                 j += i+1;
    1847                                 x.CopyVector(&(Walker->x));
    1848                                 x.KeepPeriodic(out, matrix);
    1849                                 n[i] = (int)floor(x.x[i]/cell_size[j]*(double)divisor[i]);
    1850                         }
    1851                         index = n[2] + (n[1] + n[0] * divisor[1]) * divisor[2];
    1852                         //*out << Verbose(1) << "Atom " << *Walker << " goes into cell number [" << n[0] << "," << n[1] << "," << n[2] << "] = " << index << "." << endl;
    1853                         // add copy atom to this cell
    1854                         if (CellList[index] == NULL)    // allocate molecule if not done
    1855                                 CellList[index] = new molecule(elemente);
    1856                         OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference
    1857                         //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl;
    1858                 }
    1859                 //for (int i=0;i<NumberCells;i++)
    1860                         //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl;
    1861 
    1862 
    1863                 // 3a. go through every cell
    1864                 for (N[0]=divisor[0];N[0]--;)
    1865                         for (N[1]=divisor[1];N[1]--;)
    1866                                 for (N[2]=divisor[2];N[2]--;) {
    1867                                         Index = N[2] + (N[1] + N[0] * divisor[1]) * divisor[2];
    1868                                         if (CellList[Index] != NULL) { // if there atoms in this cell
    1869                                                 //*out << Verbose(1) << "Current cell is " << Index << "." << endl;
    1870                                                 // 3b. for every atom therein
    1871                                                 Walker = CellList[Index]->start;
    1872                                                 while (Walker->next != CellList[Index]->end) {  // go through every atom
    1873                                                         Walker = Walker->next;
    1874                                                         //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl;
    1875                                                         // 3c. check for possible bond between each atom in this and every one in the 27 cells
    1876                                                         for (n[0]=-1;n[0]<=1;n[0]++)
    1877                                                                 for (n[1]=-1;n[1]<=1;n[1]++)
    1878                                                                         for (n[2]=-1;n[2]<=1;n[2]++) {
    1879                                                                                 // compute the index of this comparison cell and make it periodic
    1880                                                                                 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];
    1881                                                                                 //*out << Verbose(1) << "Number of comparison cell is " << index << "." << endl;
    1882                                                                                 if (CellList[index] != NULL) {  // if there are any atoms in this cell
    1883                                                                                         OtherWalker = CellList[index]->start;
    1884                                                                                         while(OtherWalker->next != CellList[index]->end) {      // go through every atom in this cell
    1885                                                                                                 OtherWalker = OtherWalker->next;
    1886                                                                                                 //*out << Verbose(0) << "Current comparison atom is " << *OtherWalker << "." << endl;
    1887                                                                                                 /// \todo periodic check is missing here!
    1888                                                                                                 //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl;
    1889                                                                                                 MinDistance = OtherWalker->type->CovalentRadius + Walker->type->CovalentRadius;
    1890                                                                                                 MinDistance *= (IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem;
    1891                                                                                                 MaxDistance = MinDistance + BONDTHRESHOLD;
    1892                                                                                                 MinDistance -= BONDTHRESHOLD;
    1893                                                                                                 distance = OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size);
    1894                                                                                                 if ((OtherWalker->father->nr > Walker->father->nr) && (distance <= MaxDistance*MaxDistance) && (distance >= MinDistance*MinDistance)) { // create bond if distance is smaller
    1895                                                                                                         //*out << Verbose(1) << "Adding Bond between " << *Walker << " and " << *OtherWalker << " in distance " << sqrt(distance) << "." << endl;
    1896                                                                                                         AddBond(Walker->father, OtherWalker->father, 1);        // also increases molecule::BondCount
    1897                                                                                                 } else {
    1898                                                                                                         //*out << Verbose(1) << "Not Adding: Wrong label order or distance too great." << endl;
    1899                                                                                                 }
    1900                                                                                         }
    1901                                                                                 }
    1902                                                                         }
    1903                                                 }
    1904                                         }
    1905                                 }
    1906 
    1907 
    1908 
    1909                 // 4. free the cell again
    1910                 for (int i=NumberCells;i--;)
    1911                         if (CellList[i] != NULL) {
    1912                                 delete(CellList[i]);
    1913                         }
    1914                 Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList");
    1915 
    1916                 // create the adjacency list per atom
    1917                 CreateListOfBondsPerAtom(out);
    1918 
    1919                 // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees,
    1920                 // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene
    1921                 // preferred over carbon bonds). Beforehand, we had picked the first mismatching partner, which lead to oxygenes with single instead of
    1922                 // double bonds as was expected.
    1923                 if (BondCount != 0) {
    1924                         NoCyclicBonds = 0;
    1925                         *out << Verbose(1) << "Correcting Bond degree of each bond ... ";
    1926                         do {
    1927                                 No = 0; // No acts as breakup flag (if 1 we still continue)
    1928                                 Walker = start;
    1929                                 while (Walker->next != end) { // go through every atom
    1930                                         Walker = Walker->next;
    1931                                         // count valence of first partner
    1932                                         NoBonds = 0;
    1933                                         for(j=0;j<NumberOfBondsPerAtom[Walker->nr];j++)
    1934                                                 NoBonds += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;
    1935                                         *out << Verbose(3) << "Walker " << *Walker << ": " << (int)Walker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;
    1936                                         if ((int)(Walker->type->NoValenceOrbitals) > NoBonds) { // we have a mismatch, check all bonding partners for mismatch
    1937                                                 Candidate = NULL;
    1938                                                 CandidateBondNo = -1;
    1939                                                 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through each of its bond partners
    1940                                                         OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
    1941                                                         // count valence of second partner
    1942                                                         NoBonds = 0;
    1943                                                         for(j=0;j<NumberOfBondsPerAtom[OtherWalker->nr];j++)
    1944                                                                 NoBonds += ListOfBondsPerAtom[OtherWalker->nr][j]->BondDegree;
    1945                                                         *out << Verbose(3) << "OtherWalker " << *OtherWalker << ": " << (int)OtherWalker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;
    1946                                                         if ((int)(OtherWalker->type->NoValenceOrbitals) > NoBonds) { // check if possible candidate
    1947                                                                 if ((Candidate == NULL) || (NumberOfBondsPerAtom[Candidate->nr] > NumberOfBondsPerAtom[OtherWalker->nr])) { // pick the one with fewer number of bonds first
    1948                                                                         Candidate = OtherWalker;
    1949                                                                         CandidateBondNo = i;
    1950                                                                         *out << Verbose(3) << "New candidate is " << *Candidate << "." << endl;
    1951                                                                 }
    1952                                                         }
    1953                                                 }
    1954                                                 if ((Candidate != NULL) && (CandidateBondNo != -1)) {
    1955                                                         ListOfBondsPerAtom[Walker->nr][CandidateBondNo]->BondDegree++;
    1956                                                         *out << Verbose(2) << "Increased bond degree for bond " << *ListOfBondsPerAtom[Walker->nr][CandidateBondNo] << "." << endl;
    1957                                                 } else
    1958                                                         *out << Verbose(2) << "Could not find correct degree for atom " << *Walker << "." << endl;
    1959                                                         FalseBondDegree++;
    1960                                         }
    1961                                 }
    1962                         } while (No);
    1963                 *out << " done." << endl;
    1964                 } else
    1965                         *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl;
    1966                 *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl;
    1967 
    1968                 // output bonds for debugging (if bond chain list was correctly installed)
    1969                 *out << Verbose(1) << endl << "From contents of bond chain list:";
    1970                 bond *Binder = first;
    1971                 while(Binder->next != last) {
    1972                         Binder = Binder->next;
    1973                         *out << *Binder << "\t" << endl;
    1974                 }
    1975                 *out << endl;
    1976         } else
    1977                 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl;
    1978         *out << Verbose(0) << "End of CreateAdjacencyList." << endl;
    1979         Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix");
     1801  atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL;
     1802  int No, NoBonds, CandidateBondNo;
     1803  int NumberCells, divisor[NDIM], n[NDIM], N[NDIM], index, Index, j;
     1804  molecule **CellList;
     1805  double distance, MinDistance, MaxDistance;
     1806  double *matrix = ReturnFullMatrixforSymmetric(cell_size);
     1807  Vector x;
     1808  int FalseBondDegree = 0;
     1809
     1810  BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem);
     1811  *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl;
     1812  // remove every bond from the list
     1813  if ((first->next != last) && (last->previous != first)) {  // there are bonds present
     1814    cleanup(first,last);
     1815  }
     1816
     1817  // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering)
     1818  CountAtoms(out);
     1819  *out << Verbose(1) << "AtomCount " << AtomCount << "." << endl;
     1820
     1821  if (AtomCount != 0) {
     1822    // 1. find divisor for each axis, such that a sphere with radius of at least bonddistance can be placed into each cell
     1823    j=-1;
     1824    for (int i=0;i<NDIM;i++) {
     1825      j += i+1;
     1826      divisor[i] = (int)floor(cell_size[j]/bonddistance); // take smaller value such that size of linked cell is at least bonddistance
     1827      //*out << Verbose(1) << "divisor[" << i << "]  = " << divisor[i] << "." << endl;
     1828    }
     1829    // 2a. allocate memory for the cell list
     1830    NumberCells = divisor[0]*divisor[1]*divisor[2];
     1831    *out << Verbose(1) << "Allocating " << NumberCells << " cells." << endl;
     1832    CellList = (molecule **) Malloc(sizeof(molecule *)*NumberCells, "molecule::CreateAdjacencyList - ** CellList");
     1833    for (int i=NumberCells;i--;)
     1834      CellList[i] = NULL;
     1835
     1836    // 2b. put all atoms into its corresponding list
     1837    Walker = start;
     1838    while(Walker->next != end) {
     1839      Walker = Walker->next;
     1840      //*out << Verbose(1) << "Current atom is " << *Walker << " with coordinates ";
     1841      //Walker->x.Output(out);
     1842      //*out << "." << endl;
     1843      // compute the cell by the atom's coordinates
     1844      j=-1;
     1845      for (int i=0;i<NDIM;i++) {
     1846        j += i+1;
     1847        x.CopyVector(&(Walker->x));
     1848        x.KeepPeriodic(out, matrix);
     1849        n[i] = (int)floor(x.x[i]/cell_size[j]*(double)divisor[i]);
     1850      }
     1851      index = n[2] + (n[1] + n[0] * divisor[1]) * divisor[2];
     1852      //*out << Verbose(1) << "Atom " << *Walker << " goes into cell number [" << n[0] << "," << n[1] << "," << n[2] << "] = " << index << "." << endl;
     1853      // add copy atom to this cell
     1854      if (CellList[index] == NULL)  // allocate molecule if not done
     1855        CellList[index] = new molecule(elemente);
     1856      OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference
     1857      //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl;
     1858    }
     1859    //for (int i=0;i<NumberCells;i++)
     1860      //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl;
     1861
     1862
     1863    // 3a. go through every cell
     1864    for (N[0]=divisor[0];N[0]--;)
     1865      for (N[1]=divisor[1];N[1]--;)
     1866        for (N[2]=divisor[2];N[2]--;) {
     1867          Index = N[2] + (N[1] + N[0] * divisor[1]) * divisor[2];
     1868          if (CellList[Index] != NULL) { // if there atoms in this cell
     1869            //*out << Verbose(1) << "Current cell is " << Index << "." << endl;
     1870            // 3b. for every atom therein
     1871            Walker = CellList[Index]->start;
     1872            while (Walker->next != CellList[Index]->end) {  // go through every atom
     1873              Walker = Walker->next;
     1874              //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl;
     1875              // 3c. check for possible bond between each atom in this and every one in the 27 cells
     1876              for (n[0]=-1;n[0]<=1;n[0]++)
     1877                for (n[1]=-1;n[1]<=1;n[1]++)
     1878                  for (n[2]=-1;n[2]<=1;n[2]++) {
     1879                    // compute the index of this comparison cell and make it periodic
     1880                    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];
     1881                    //*out << Verbose(1) << "Number of comparison cell is " << index << "." << endl;
     1882                    if (CellList[index] != NULL) {  // if there are any atoms in this cell
     1883                      OtherWalker = CellList[index]->start;
     1884                      while(OtherWalker->next != CellList[index]->end) {  // go through every atom in this cell
     1885                        OtherWalker = OtherWalker->next;
     1886                        //*out << Verbose(0) << "Current comparison atom is " << *OtherWalker << "." << endl;
     1887                        /// \todo periodic check is missing here!
     1888                        //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl;
     1889                        MinDistance = OtherWalker->type->CovalentRadius + Walker->type->CovalentRadius;
     1890                        MinDistance *= (IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem;
     1891                        MaxDistance = MinDistance + BONDTHRESHOLD;
     1892                        MinDistance -= BONDTHRESHOLD;
     1893                        distance = OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size);
     1894                        if ((OtherWalker->father->nr > Walker->father->nr) && (distance <= MaxDistance*MaxDistance) && (distance >= MinDistance*MinDistance)) { // create bond if distance is smaller
     1895                          //*out << Verbose(1) << "Adding Bond between " << *Walker << " and " << *OtherWalker << " in distance " << sqrt(distance) << "." << endl;
     1896                          AddBond(Walker->father, OtherWalker->father, 1);  // also increases molecule::BondCount
     1897                        } else {
     1898                          //*out << Verbose(1) << "Not Adding: Wrong label order or distance too great." << endl;
     1899                        }
     1900                      }
     1901                    }
     1902                  }
     1903            }
     1904          }
     1905        }
     1906
     1907
     1908
     1909    // 4. free the cell again
     1910    for (int i=NumberCells;i--;)
     1911      if (CellList[i] != NULL) {
     1912        delete(CellList[i]);
     1913      }
     1914    Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList");
     1915
     1916    // create the adjacency list per atom
     1917    CreateListOfBondsPerAtom(out);
     1918
     1919    // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees,
     1920    // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene
     1921    // preferred over carbon bonds). Beforehand, we had picked the first mismatching partner, which lead to oxygenes with single instead of
     1922    // double bonds as was expected.
     1923    if (BondCount != 0) {
     1924      NoCyclicBonds = 0;
     1925      *out << Verbose(1) << "Correcting Bond degree of each bond ... ";
     1926      do {
     1927        No = 0; // No acts as breakup flag (if 1 we still continue)
     1928        Walker = start;
     1929        while (Walker->next != end) { // go through every atom
     1930          Walker = Walker->next;
     1931          // count valence of first partner
     1932          NoBonds = 0;
     1933          for(j=0;j<NumberOfBondsPerAtom[Walker->nr];j++)
     1934            NoBonds += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;
     1935          *out << Verbose(3) << "Walker " << *Walker << ": " << (int)Walker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;
     1936          if ((int)(Walker->type->NoValenceOrbitals) > NoBonds) { // we have a mismatch, check all bonding partners for mismatch
     1937            Candidate = NULL;
     1938            CandidateBondNo = -1;
     1939            for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through each of its bond partners
     1940              OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
     1941              // count valence of second partner
     1942              NoBonds = 0;
     1943              for(j=0;j<NumberOfBondsPerAtom[OtherWalker->nr];j++)
     1944                NoBonds += ListOfBondsPerAtom[OtherWalker->nr][j]->BondDegree;
     1945              *out << Verbose(3) << "OtherWalker " << *OtherWalker << ": " << (int)OtherWalker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;
     1946              if ((int)(OtherWalker->type->NoValenceOrbitals) > NoBonds) { // check if possible candidate
     1947                if ((Candidate == NULL) || (NumberOfBondsPerAtom[Candidate->nr] > NumberOfBondsPerAtom[OtherWalker->nr])) { // pick the one with fewer number of bonds first
     1948                  Candidate = OtherWalker;
     1949                  CandidateBondNo = i;
     1950                  *out << Verbose(3) << "New candidate is " << *Candidate << "." << endl;
     1951                }
     1952              }
     1953            }
     1954            if ((Candidate != NULL) && (CandidateBondNo != -1)) {
     1955              ListOfBondsPerAtom[Walker->nr][CandidateBondNo]->BondDegree++;
     1956              *out << Verbose(2) << "Increased bond degree for bond " << *ListOfBondsPerAtom[Walker->nr][CandidateBondNo] << "." << endl;
     1957            } else
     1958              *out << Verbose(2) << "Could not find correct degree for atom " << *Walker << "." << endl;
     1959              FalseBondDegree++;
     1960          }
     1961        }
     1962      } while (No);
     1963    *out << " done." << endl;
     1964    } else
     1965      *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl;
     1966    *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl;
     1967
     1968    // output bonds for debugging (if bond chain list was correctly installed)
     1969    *out << Verbose(1) << endl << "From contents of bond chain list:";
     1970    bond *Binder = first;
     1971    while(Binder->next != last) {
     1972      Binder = Binder->next;
     1973      *out << *Binder << "\t" << endl;
     1974    }
     1975    *out << endl;
     1976  } else
     1977    *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl;
     1978  *out << Verbose(0) << "End of CreateAdjacencyList." << endl;
     1979  Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix");
    19801980
    19811981};
     
    19931993MoleculeLeafClass * molecule::DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack)
    19941994{
    1995         class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);
    1996         BackEdgeStack = new StackClass<bond *> (BondCount);
    1997         MoleculeLeafClass *SubGraphs = new MoleculeLeafClass(NULL);
    1998         MoleculeLeafClass *LeafWalker = SubGraphs;
    1999         int CurrentGraphNr = 0, OldGraphNr;
    2000         int ComponentNumber = 0;
    2001         atom *Walker = NULL, *OtherAtom = NULL, *Root = start->next;
    2002         bond *Binder = NULL;
    2003         bool BackStepping = false;
    2004 
    2005         *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl;
    2006 
    2007         ResetAllBondsToUnused();
    2008         ResetAllAtomNumbers();
    2009         InitComponentNumbers();
    2010         BackEdgeStack->ClearStack();
    2011         while (Root != end) { // if there any atoms at all
    2012                 // (1) mark all edges unused, empty stack, set atom->GraphNr = 0 for all
    2013                 AtomStack->ClearStack();
    2014 
    2015                 // put into new subgraph molecule and add this to list of subgraphs
    2016                 LeafWalker = new MoleculeLeafClass(LeafWalker);
    2017                 LeafWalker->Leaf = new molecule(elemente);
    2018                 LeafWalker->Leaf->AddCopyAtom(Root);
    2019 
    2020                 OldGraphNr = CurrentGraphNr;
    2021                 Walker = Root;
    2022                 do { // (10)
    2023                         do { // (2) set number and Lowpoint of Atom to i, increase i, push current atom
    2024                                 if (!BackStepping) { // if we don't just return from (8)
    2025                                         Walker->GraphNr = CurrentGraphNr;
    2026                                         Walker->LowpointNr = CurrentGraphNr;
    2027                                         *out << Verbose(1) << "Setting Walker[" << Walker->Name << "]'s number to " << Walker->GraphNr << " with Lowpoint " << Walker->LowpointNr << "." << endl;
    2028                                         AtomStack->Push(Walker);
    2029                                         CurrentGraphNr++;
    2030                                 }
    2031                                 do { // (3) if Walker has no unused egdes, go to (5)
    2032                                         BackStepping = false; // reset backstepping flag for (8)
    2033                                         if (Binder == NULL) // if we don't just return from (11), Binder is already set to next unused
    2034                                                 Binder = FindNextUnused(Walker);
    2035                                         if (Binder == NULL)
    2036                                                 break;
    2037                                         *out << Verbose(2) << "Current Unused Bond is " << *Binder << "." << endl;
    2038                                         // (4) Mark Binder used, ...
    2039                                         Binder->MarkUsed(black);
    2040                                         OtherAtom = Binder->GetOtherAtom(Walker);
    2041                                         *out << Verbose(2) << "(4) OtherAtom is " << OtherAtom->Name << "." << endl;
    2042                                         if (OtherAtom->GraphNr != -1) {
    2043                                                 // (4a) ... if "other" atom has been visited (GraphNr != 0), set lowpoint to minimum of both, go to (3)
    2044                                                 Binder->Type = BackEdge;
    2045                                                 BackEdgeStack->Push(Binder);
    2046                                                 Walker->LowpointNr = ( Walker->LowpointNr < OtherAtom->GraphNr ) ? Walker->LowpointNr : OtherAtom->GraphNr;
    2047                                                 *out << Verbose(3) << "(4a) Visited: Setting Lowpoint of Walker[" << Walker->Name << "] to " << Walker->LowpointNr << "." << endl;
    2048                                         } else {
    2049                                                 // (4b) ... otherwise set OtherAtom as Ancestor of Walker and Walker as OtherAtom, go to (2)
    2050                                                 Binder->Type = TreeEdge;
    2051                                                 OtherAtom->Ancestor = Walker;
    2052                                                 Walker = OtherAtom;
    2053                                                 *out << Verbose(3) << "(4b) Not Visited: OtherAtom[" << OtherAtom->Name << "]'s Ancestor is now " << OtherAtom->Ancestor->Name << ", Walker is OtherAtom " << OtherAtom->Name << "." << endl;
    2054                                                 break;
    2055                                         }
    2056                                         Binder = NULL;
    2057                                 } while (1);    // (3)
    2058                                 if (Binder == NULL) {
    2059                                         *out << Verbose(2) << "No more Unused Bonds." << endl;
    2060                                         break;
    2061                                 } else
    2062                                         Binder = NULL;
    2063                         } while (1);    // (2)
    2064 
    2065                         // 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!
    2066                         if ((Walker == Root) && (Binder == NULL))
    2067                                 break;
    2068 
    2069                         // (5) if Ancestor of Walker is ...
    2070                         *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl;
    2071                         if (Walker->Ancestor->GraphNr != Root->GraphNr) {
    2072                                 // (6)  (Ancestor of Walker is not Root)
    2073                                 if (Walker->LowpointNr < Walker->Ancestor->GraphNr) {
    2074                                         // (6a) set Ancestor's Lowpoint number to minimum of of its Ancestor and itself, go to Step(8)
    2075                                         Walker->Ancestor->LowpointNr = (Walker->Ancestor->LowpointNr < Walker->LowpointNr) ? Walker->Ancestor->LowpointNr : Walker->LowpointNr;
    2076                                         *out << Verbose(2) << "(6) Setting Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s Lowpoint to " << Walker->Ancestor->LowpointNr << "." << endl;
    2077                                 } else {
    2078                                         // (7) (Ancestor of Walker is a separating vertex, remove all from stack till Walker (including), these and Ancestor form a component
    2079                                         Walker->Ancestor->SeparationVertex = true;
    2080                                         *out << Verbose(2) << "(7) Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s is a separating vertex, creating component." << endl;
    2081                                         SetNextComponentNumber(Walker->Ancestor, ComponentNumber);
    2082                                         *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Ancestor's Compont is " << ComponentNumber << "." << endl;
    2083                                         SetNextComponentNumber(Walker, ComponentNumber);
    2084                                         *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Compont is " << ComponentNumber << "." << endl;
    2085                                         do {
    2086                                                 OtherAtom = AtomStack->PopLast();
    2087                                                 LeafWalker->Leaf->AddCopyAtom(OtherAtom);
    2088                                                 SetNextComponentNumber(OtherAtom, ComponentNumber);
    2089                                                 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;
    2090                                         } while (OtherAtom != Walker);
    2091                                         ComponentNumber++;
    2092                                 }
    2093                                 // (8) Walker becomes its Ancestor, go to (3)
    2094                                 *out << Verbose(2) << "(8) Walker[" << Walker->Name << "] is now its Ancestor " << Walker->Ancestor->Name << ", backstepping. " << endl;
    2095                                 Walker = Walker->Ancestor;
    2096                                 BackStepping = true;
    2097                         }
    2098                         if (!BackStepping) {    // coming from (8) want to go to (3)
    2099                                 // (9) remove all from stack till Walker (including), these and Root form a component
    2100                                 AtomStack->Output(out);
    2101                                 SetNextComponentNumber(Root, ComponentNumber);
    2102                                 *out << Verbose(3) << "(9) Root[" << Root->Name << "]'s Component is " << ComponentNumber << "." << endl;
    2103                                 SetNextComponentNumber(Walker, ComponentNumber);
    2104                                 *out << Verbose(3) << "(9) Walker[" << Walker->Name << "]'s Component is " << ComponentNumber << "." << endl;
    2105                                 do {
    2106                                         OtherAtom = AtomStack->PopLast();
    2107                                         LeafWalker->Leaf->AddCopyAtom(OtherAtom);
    2108                                         SetNextComponentNumber(OtherAtom, ComponentNumber);
    2109                                         *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;
    2110                                 } while (OtherAtom != Walker);
    2111                                 ComponentNumber++;
    2112 
    2113                                 // (11) Root is separation vertex,      set Walker to Root and go to (4)
    2114                                 Walker = Root;
    2115                                 Binder = FindNextUnused(Walker);
    2116                                 *out << Verbose(1) << "(10) Walker is Root[" << Root->Name << "], next Unused Bond is " << Binder << "." << endl;
    2117                                 if (Binder != NULL) { // Root is separation vertex
    2118                                         *out << Verbose(1) << "(11) Root is a separation vertex." << endl;
    2119                                         Walker->SeparationVertex = true;
    2120                                 }
    2121                         }
    2122                 } while ((BackStepping) || (Binder != NULL)); // (10) halt only if Root has no unused edges
    2123 
    2124                 // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph
    2125                 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl;
    2126                 LeafWalker->Leaf->Output(out);
    2127                 *out << endl;
    2128 
    2129                 // step on to next root
    2130                 while ((Root != end) && (Root->GraphNr != -1)) {
    2131                         //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl;
    2132                         if (Root->GraphNr != -1) // if already discovered, step on
    2133                                 Root = Root->next;
    2134                 }
    2135         }
    2136         // set cyclic bond criterium on "same LP" basis
    2137         Binder = first;
    2138         while(Binder->next != last) {
    2139                 Binder = Binder->next;
    2140                 if (Binder->rightatom->LowpointNr == Binder->leftatom->LowpointNr) { // cyclic ??
    2141                         Binder->Cyclic = true;
    2142                         NoCyclicBonds++;
    2143                 }
    2144         }
    2145 
    2146 
    2147         *out << Verbose(1) << "Final graph info for each atom is:" << endl;
    2148         Walker = start;
    2149         while (Walker->next != end) {
    2150                 Walker = Walker->next;
    2151                 *out << Verbose(2) << "Atom " << Walker->Name << " is " << ((Walker->SeparationVertex) ? "a" : "not a") << " separation vertex, components are ";
    2152                 OutputComponentNumber(out, Walker);
    2153                 *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl;
    2154         }
    2155 
    2156         *out << Verbose(1) << "Final graph info for each bond is:" << endl;
    2157         Binder = first;
    2158         while(Binder->next != last) {
    2159                 Binder = Binder->next;
    2160                 *out << Verbose(2) << ((Binder->Type == TreeEdge) ? "TreeEdge " : "BackEdge ") << *Binder << ": <";
    2161                 *out << ((Binder->leftatom->SeparationVertex) ? "SP," : "") << "L" << Binder->leftatom->LowpointNr << " G" << Binder->leftatom->GraphNr << " Comp.";
    2162                 OutputComponentNumber(out, Binder->leftatom);
    2163                 *out << " ===   ";
    2164                 *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp.";
    2165                 OutputComponentNumber(out, Binder->rightatom);
    2166                 *out << ">." << endl;
    2167                 if (Binder->Cyclic) // cyclic ??
    2168                         *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl;
    2169         }
    2170 
    2171         // free all and exit
    2172         delete(AtomStack);
    2173         *out << Verbose(0) << "End of DepthFirstSearchAnalysis" << endl;
    2174         return SubGraphs;
     1995  class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);
     1996  BackEdgeStack = new StackClass<bond *> (BondCount);
     1997  MoleculeLeafClass *SubGraphs = new MoleculeLeafClass(NULL);
     1998  MoleculeLeafClass *LeafWalker = SubGraphs;
     1999  int CurrentGraphNr = 0, OldGraphNr;
     2000  int ComponentNumber = 0;
     2001  atom *Walker = NULL, *OtherAtom = NULL, *Root = start->next;
     2002  bond *Binder = NULL;
     2003  bool BackStepping = false;
     2004
     2005  *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl;
     2006
     2007  ResetAllBondsToUnused();
     2008  ResetAllAtomNumbers();
     2009  InitComponentNumbers();
     2010  BackEdgeStack->ClearStack();
     2011  while (Root != end) { // if there any atoms at all
     2012    // (1) mark all edges unused, empty stack, set atom->GraphNr = 0 for all
     2013    AtomStack->ClearStack();
     2014
     2015    // put into new subgraph molecule and add this to list of subgraphs
     2016    LeafWalker = new MoleculeLeafClass(LeafWalker);
     2017    LeafWalker->Leaf = new molecule(elemente);
     2018    LeafWalker->Leaf->AddCopyAtom(Root);
     2019
     2020    OldGraphNr = CurrentGraphNr;
     2021    Walker = Root;
     2022    do { // (10)
     2023      do { // (2) set number and Lowpoint of Atom to i, increase i, push current atom
     2024        if (!BackStepping) { // if we don't just return from (8)
     2025          Walker->GraphNr = CurrentGraphNr;
     2026          Walker->LowpointNr = CurrentGraphNr;
     2027          *out << Verbose(1) << "Setting Walker[" << Walker->Name << "]'s number to " << Walker->GraphNr << " with Lowpoint " << Walker->LowpointNr << "." << endl;
     2028          AtomStack->Push(Walker);
     2029          CurrentGraphNr++;
     2030        }
     2031        do { // (3) if Walker has no unused egdes, go to (5)
     2032          BackStepping = false; // reset backstepping flag for (8)
     2033          if (Binder == NULL) // if we don't just return from (11), Binder is already set to next unused
     2034            Binder = FindNextUnused(Walker);
     2035          if (Binder == NULL)
     2036            break;
     2037          *out << Verbose(2) << "Current Unused Bond is " << *Binder << "." << endl;
     2038          // (4) Mark Binder used, ...
     2039          Binder->MarkUsed(black);
     2040          OtherAtom = Binder->GetOtherAtom(Walker);
     2041          *out << Verbose(2) << "(4) OtherAtom is " << OtherAtom->Name << "." << endl;
     2042          if (OtherAtom->GraphNr != -1) {
     2043            // (4a) ... if "other" atom has been visited (GraphNr != 0), set lowpoint to minimum of both, go to (3)
     2044            Binder->Type = BackEdge;
     2045            BackEdgeStack->Push(Binder);
     2046            Walker->LowpointNr = ( Walker->LowpointNr < OtherAtom->GraphNr ) ? Walker->LowpointNr : OtherAtom->GraphNr;
     2047            *out << Verbose(3) << "(4a) Visited: Setting Lowpoint of Walker[" << Walker->Name << "] to " << Walker->LowpointNr << "." << endl;
     2048          } else {
     2049            // (4b) ... otherwise set OtherAtom as Ancestor of Walker and Walker as OtherAtom, go to (2)
     2050            Binder->Type = TreeEdge;
     2051            OtherAtom->Ancestor = Walker;
     2052            Walker = OtherAtom;
     2053            *out << Verbose(3) << "(4b) Not Visited: OtherAtom[" << OtherAtom->Name << "]'s Ancestor is now " << OtherAtom->Ancestor->Name << ", Walker is OtherAtom " << OtherAtom->Name << "." << endl;
     2054            break;
     2055          }
     2056          Binder = NULL;
     2057        } while (1);  // (3)
     2058        if (Binder == NULL) {
     2059          *out << Verbose(2) << "No more Unused Bonds." << endl;
     2060          break;
     2061        } else
     2062          Binder = NULL;
     2063      } while (1);  // (2)
     2064
     2065      // 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!
     2066      if ((Walker == Root) && (Binder == NULL))
     2067        break;
     2068
     2069      // (5) if Ancestor of Walker is ...
     2070      *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl;
     2071      if (Walker->Ancestor->GraphNr != Root->GraphNr) {
     2072        // (6)  (Ancestor of Walker is not Root)
     2073        if (Walker->LowpointNr < Walker->Ancestor->GraphNr) {
     2074          // (6a) set Ancestor's Lowpoint number to minimum of of its Ancestor and itself, go to Step(8)
     2075          Walker->Ancestor->LowpointNr = (Walker->Ancestor->LowpointNr < Walker->LowpointNr) ? Walker->Ancestor->LowpointNr : Walker->LowpointNr;
     2076          *out << Verbose(2) << "(6) Setting Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s Lowpoint to " << Walker->Ancestor->LowpointNr << "." << endl;
     2077        } else {
     2078          // (7) (Ancestor of Walker is a separating vertex, remove all from stack till Walker (including), these and Ancestor form a component
     2079          Walker->Ancestor->SeparationVertex = true;
     2080          *out << Verbose(2) << "(7) Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s is a separating vertex, creating component." << endl;
     2081          SetNextComponentNumber(Walker->Ancestor, ComponentNumber);
     2082          *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Ancestor's Compont is " << ComponentNumber << "." << endl;
     2083          SetNextComponentNumber(Walker, ComponentNumber);
     2084          *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Compont is " << ComponentNumber << "." << endl;
     2085          do {
     2086            OtherAtom = AtomStack->PopLast();
     2087            LeafWalker->Leaf->AddCopyAtom(OtherAtom);
     2088            SetNextComponentNumber(OtherAtom, ComponentNumber);
     2089            *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;
     2090          } while (OtherAtom != Walker);
     2091          ComponentNumber++;
     2092        }
     2093        // (8) Walker becomes its Ancestor, go to (3)
     2094        *out << Verbose(2) << "(8) Walker[" << Walker->Name << "] is now its Ancestor " << Walker->Ancestor->Name << ", backstepping. " << endl;
     2095        Walker = Walker->Ancestor;
     2096        BackStepping = true;
     2097      }
     2098      if (!BackStepping) {  // coming from (8) want to go to (3)
     2099        // (9) remove all from stack till Walker (including), these and Root form a component
     2100        AtomStack->Output(out);
     2101        SetNextComponentNumber(Root, ComponentNumber);
     2102        *out << Verbose(3) << "(9) Root[" << Root->Name << "]'s Component is " << ComponentNumber << "." << endl;
     2103        SetNextComponentNumber(Walker, ComponentNumber);
     2104        *out << Verbose(3) << "(9) Walker[" << Walker->Name << "]'s Component is " << ComponentNumber << "." << endl;
     2105        do {
     2106          OtherAtom = AtomStack->PopLast();
     2107          LeafWalker->Leaf->AddCopyAtom(OtherAtom);
     2108          SetNextComponentNumber(OtherAtom, ComponentNumber);
     2109          *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;
     2110        } while (OtherAtom != Walker);
     2111        ComponentNumber++;
     2112
     2113        // (11) Root is separation vertex,  set Walker to Root and go to (4)
     2114        Walker = Root;
     2115        Binder = FindNextUnused(Walker);
     2116        *out << Verbose(1) << "(10) Walker is Root[" << Root->Name << "], next Unused Bond is " << Binder << "." << endl;
     2117        if (Binder != NULL) { // Root is separation vertex
     2118          *out << Verbose(1) << "(11) Root is a separation vertex." << endl;
     2119          Walker->SeparationVertex = true;
     2120        }
     2121      }
     2122    } while ((BackStepping) || (Binder != NULL)); // (10) halt only if Root has no unused edges
     2123
     2124    // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph
     2125    *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl;
     2126    LeafWalker->Leaf->Output(out);
     2127    *out << endl;
     2128
     2129    // step on to next root
     2130    while ((Root != end) && (Root->GraphNr != -1)) {
     2131      //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl;
     2132      if (Root->GraphNr != -1) // if already discovered, step on
     2133        Root = Root->next;
     2134    }
     2135  }
     2136  // set cyclic bond criterium on "same LP" basis
     2137  Binder = first;
     2138  while(Binder->next != last) {
     2139    Binder = Binder->next;
     2140    if (Binder->rightatom->LowpointNr == Binder->leftatom->LowpointNr) { // cyclic ??
     2141      Binder->Cyclic = true;
     2142      NoCyclicBonds++;
     2143    }
     2144  }
     2145
     2146
     2147  *out << Verbose(1) << "Final graph info for each atom is:" << endl;
     2148  Walker = start;
     2149  while (Walker->next != end) {
     2150    Walker = Walker->next;
     2151    *out << Verbose(2) << "Atom " << Walker->Name << " is " << ((Walker->SeparationVertex) ? "a" : "not a") << " separation vertex, components are ";
     2152    OutputComponentNumber(out, Walker);
     2153    *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl;
     2154  }
     2155
     2156  *out << Verbose(1) << "Final graph info for each bond is:" << endl;
     2157  Binder = first;
     2158  while(Binder->next != last) {
     2159    Binder = Binder->next;
     2160    *out << Verbose(2) << ((Binder->Type == TreeEdge) ? "TreeEdge " : "BackEdge ") << *Binder << ": <";
     2161    *out << ((Binder->leftatom->SeparationVertex) ? "SP," : "") << "L" << Binder->leftatom->LowpointNr << " G" << Binder->leftatom->GraphNr << " Comp.";
     2162    OutputComponentNumber(out, Binder->leftatom);
     2163    *out << " ===  ";
     2164    *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp.";
     2165    OutputComponentNumber(out, Binder->rightatom);
     2166    *out << ">." << endl;
     2167    if (Binder->Cyclic) // cyclic ??
     2168      *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl;
     2169  }
     2170
     2171  // free all and exit
     2172  delete(AtomStack);
     2173  *out << Verbose(0) << "End of DepthFirstSearchAnalysis" << endl;
     2174  return SubGraphs;
    21752175};
    21762176
     
    21852185 * \todo BFS from the not-same-LP to find back to starting point of tributary cycle over more than one bond
    21862186 */
    2187 void molecule::CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> *        BackEdgeStack, int *&MinimumRingSize)
    2188 {
    2189         atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CyclicStructureAnalysis: **PredecessorList");
    2190         int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList");
    2191         enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList");
    2192         class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount);        // will hold the current ring
    2193         class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount);    // contains all "touched" atoms (that need to be reset after BFS loop)
    2194         atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL;
    2195         bond *Binder = NULL, *BackEdge = NULL;
    2196         int RingSize, NumCycles, MinRingSize = -1;
    2197 
    2198         // initialise each vertex as white with no predecessor, empty queue, color Root lightgray
    2199         for (int i=AtomCount;i--;) {
    2200                 PredecessorList[i] = NULL;
    2201                 ShortestPathList[i] = -1;
    2202                 ColorList[i] = white;
    2203         }
    2204 
    2205         *out << Verbose(1) << "Back edge list - ";
    2206         BackEdgeStack->Output(out);
    2207 
    2208         *out << Verbose(1) << "Analysing cycles ... " << endl;
    2209         NumCycles = 0;
    2210         while (!BackEdgeStack->IsEmpty()) {
    2211                 BackEdge = BackEdgeStack->PopFirst();
    2212                 // this is the target
    2213                 Root = BackEdge->leftatom;
    2214                 // this is the source point
    2215                 Walker = BackEdge->rightatom;
    2216                 ShortestPathList[Walker->nr] = 0;
    2217                 BFSStack->ClearStack(); // start with empty BFS stack
    2218                 BFSStack->Push(Walker);
    2219                 TouchedStack->Push(Walker);
    2220                 *out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;
    2221                 OtherAtom = NULL;
    2222                 do {    // look for Root
    2223                         Walker = BFSStack->PopFirst();
    2224                         *out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;
    2225                         for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
    2226                                 Binder = ListOfBondsPerAtom[Walker->nr][i];
    2227                                 if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder)
    2228                                         OtherAtom = Binder->GetOtherAtom(Walker);
     2187void molecule::CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> *  BackEdgeStack, int *&MinimumRingSize)
     2188{
     2189  atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CyclicStructureAnalysis: **PredecessorList");
     2190  int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList");
     2191  enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList");
     2192  class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount);  // will hold the current ring
     2193  class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount);  // contains all "touched" atoms (that need to be reset after BFS loop)
     2194  atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL;
     2195  bond *Binder = NULL, *BackEdge = NULL;
     2196  int RingSize, NumCycles, MinRingSize = -1;
     2197
     2198  // initialise each vertex as white with no predecessor, empty queue, color Root lightgray
     2199  for (int i=AtomCount;i--;) {
     2200    PredecessorList[i] = NULL;
     2201    ShortestPathList[i] = -1;
     2202    ColorList[i] = white;
     2203  }
     2204
     2205  *out << Verbose(1) << "Back edge list - ";
     2206  BackEdgeStack->Output(out);
     2207
     2208  *out << Verbose(1) << "Analysing cycles ... " << endl;
     2209  NumCycles = 0;
     2210  while (!BackEdgeStack->IsEmpty()) {
     2211    BackEdge = BackEdgeStack->PopFirst();
     2212    // this is the target
     2213    Root = BackEdge->leftatom;
     2214    // this is the source point
     2215    Walker = BackEdge->rightatom;
     2216    ShortestPathList[Walker->nr] = 0;
     2217    BFSStack->ClearStack();  // start with empty BFS stack
     2218    BFSStack->Push(Walker);
     2219    TouchedStack->Push(Walker);
     2220    *out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;
     2221    OtherAtom = NULL;
     2222    do {  // look for Root
     2223      Walker = BFSStack->PopFirst();
     2224      *out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;
     2225      for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
     2226        Binder = ListOfBondsPerAtom[Walker->nr][i];
     2227        if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder)
     2228          OtherAtom = Binder->GetOtherAtom(Walker);
    22292229#ifdef ADDHYDROGEN
    2230                                         if (OtherAtom->type->Z != 1) {
     2230          if (OtherAtom->type->Z != 1) {
    22312231#endif
    2232                                                 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
    2233                                                 if (ColorList[OtherAtom->nr] == white) {
    2234                                                         TouchedStack->Push(OtherAtom);
    2235                                                         ColorList[OtherAtom->nr] = lightgray;
    2236                                                         PredecessorList[OtherAtom->nr] = Walker;        // Walker is the predecessor
    2237                                                         ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
    2238                                                         *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;
    2239                                                         //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance
    2240                                                                 *out << Verbose(3) << "Putting OtherAtom into queue." << endl;
    2241                                                                 BFSStack->Push(OtherAtom);
    2242                                                         //}
    2243                                                 } else {
    2244                                                         *out << Verbose(3) << "Not Adding, has already been visited." << endl;
    2245                                                 }
    2246                                                 if (OtherAtom == Root)
    2247                                                         break;
     2232            *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
     2233            if (ColorList[OtherAtom->nr] == white) {
     2234              TouchedStack->Push(OtherAtom);
     2235              ColorList[OtherAtom->nr] = lightgray;
     2236              PredecessorList[OtherAtom->nr] = Walker;  // Walker is the predecessor
     2237              ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
     2238              *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;
     2239              //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance
     2240                *out << Verbose(3) << "Putting OtherAtom into queue." << endl;
     2241                BFSStack->Push(OtherAtom);
     2242              //}
     2243            } else {
     2244              *out << Verbose(3) << "Not Adding, has already been visited." << endl;
     2245            }
     2246            if (OtherAtom == Root)
     2247              break;
    22482248#ifdef ADDHYDROGEN
    2249                                         } else {
    2250                                                 *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl;
    2251                                                 ColorList[OtherAtom->nr] = black;
    2252                                         }
     2249          } else {
     2250            *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl;
     2251            ColorList[OtherAtom->nr] = black;
     2252          }
    22532253#endif
    2254                                 } else {
    2255                                         *out << Verbose(2) << "Bond " << *Binder << " not Visiting, is the back edge." << endl;
    2256                                 }
    2257                         }
    2258                         ColorList[Walker->nr] = black;
    2259                         *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
    2260                         if (OtherAtom == Root) { // if we have found the root, check whether this cycle wasn't already found beforehand
    2261                                 // step through predecessor list
    2262                                 while (OtherAtom != BackEdge->rightatom) {
    2263                                         if (!OtherAtom->GetTrueFather()->IsCyclic)      // if one bond in the loop is not marked as cyclic, we haven't found this cycle yet
    2264                                                 break;
    2265                                         else
    2266                                                 OtherAtom = PredecessorList[OtherAtom->nr];
    2267                                 }
    2268                                 if (OtherAtom == BackEdge->rightatom) { // if each atom in found cycle is cyclic, loop's been found before already
    2269                                         *out << Verbose(3) << "This cycle was already found before, skipping and removing seeker from search." << endl;\
    2270                                         do {
    2271                                                 OtherAtom = TouchedStack->PopLast();
    2272                                                 if (PredecessorList[OtherAtom->nr] == Walker) {
    2273                                                         *out << Verbose(4) << "Removing " << *OtherAtom << " from lists and stacks." << endl;
    2274                                                         PredecessorList[OtherAtom->nr] = NULL;
    2275                                                         ShortestPathList[OtherAtom->nr] = -1;
    2276                                                         ColorList[OtherAtom->nr] = white;
    2277                                                         BFSStack->RemoveItem(OtherAtom);
    2278                                                 }
    2279                                         } while ((!TouchedStack->IsEmpty()) && (PredecessorList[OtherAtom->nr] == NULL));
    2280                                         TouchedStack->Push(OtherAtom);  // last was wrongly popped
    2281                                         OtherAtom = BackEdge->rightatom; // set to not Root
    2282                                 } else
    2283                                         OtherAtom = Root;
    2284                         }
    2285                 } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr])));
    2286 
    2287                 if (OtherAtom == Root) {
    2288                         // now climb back the predecessor list and thus find the cycle members
    2289                         NumCycles++;
    2290                         RingSize = 1;
    2291                         Root->GetTrueFather()->IsCyclic = true;
    2292                         *out << Verbose(1) << "Found ring contains: ";
    2293                         Walker = Root;
    2294                         while (Walker != BackEdge->rightatom) {
    2295                                 *out << Walker->Name << " <-> ";
    2296                                 Walker = PredecessorList[Walker->nr];
    2297                                 Walker->GetTrueFather()->IsCyclic = true;
    2298                                 RingSize++;
    2299                         }
    2300                         *out << Walker->Name << "       with a length of " << RingSize << "." << endl << endl;
    2301                         // walk through all and set MinimumRingSize
    2302                         Walker = Root;
    2303                         MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;
    2304                         while (Walker != BackEdge->rightatom) {
    2305                                 Walker = PredecessorList[Walker->nr];
    2306                                 if (RingSize < MinimumRingSize[Walker->GetTrueFather()->nr])
    2307                                         MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;
    2308                         }
    2309                         if ((RingSize < MinRingSize) || (MinRingSize == -1))
    2310                                 MinRingSize = RingSize;
    2311                 } else {
    2312                         *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl;
    2313                 }
    2314 
    2315                 // now clean the lists
    2316                 while (!TouchedStack->IsEmpty()){
    2317                         Walker = TouchedStack->PopFirst();
    2318                         PredecessorList[Walker->nr] = NULL;
    2319                         ShortestPathList[Walker->nr] = -1;
    2320                         ColorList[Walker->nr] = white;
    2321                 }
    2322         }
    2323         if (MinRingSize != -1) {
    2324                 // go over all atoms
    2325                 Root = start;
    2326                 while(Root->next != end) {
    2327                         Root = Root->next;
    2328 
    2329                         if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is
    2330                                 Walker = Root;
    2331                                 ShortestPathList[Walker->nr] = 0;
    2332                                 BFSStack->ClearStack(); // start with empty BFS stack
    2333                                 BFSStack->Push(Walker);
    2334                                 TouchedStack->Push(Walker);
    2335                                 //*out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;
    2336                                 OtherAtom = Walker;
    2337                                 while (OtherAtom != NULL) {     // look for Root
    2338                                         Walker = BFSStack->PopFirst();
    2339                                         //*out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;
    2340                                         for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
    2341                                                 Binder = ListOfBondsPerAtom[Walker->nr][i];
    2342                                                 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
    2343                                                         OtherAtom = Binder->GetOtherAtom(Walker);
    2344                                                         //*out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
    2345                                                         if (ColorList[OtherAtom->nr] == white) {
    2346                                                                 TouchedStack->Push(OtherAtom);
    2347                                                                 ColorList[OtherAtom->nr] = lightgray;
    2348                                                                 PredecessorList[OtherAtom->nr] = Walker;        // Walker is the predecessor
    2349                                                                 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
    2350                                                                 //*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;
    2351                                                                 if (OtherAtom->GetTrueFather()->IsCyclic) { // if the other atom is connected to a ring
    2352                                                                         MinimumRingSize[Root->GetTrueFather()->nr] = ShortestPathList[OtherAtom->nr]+MinimumRingSize[OtherAtom->GetTrueFather()->nr];
    2353                                                                         OtherAtom = NULL; //break;
    2354                                                                         break;
    2355                                                                 } else
    2356                                                                         BFSStack->Push(OtherAtom);
    2357                                                         } else {
    2358                                                                 //*out << Verbose(3) << "Not Adding, has already been visited." << endl;
    2359                                                         }
    2360                                                 } else {
    2361                                                         //*out << Verbose(3) << "Not Visiting, is a back edge." << endl;
    2362                                                 }
    2363                                         }
    2364                                         ColorList[Walker->nr] = black;
    2365                                         //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
    2366                                 }
    2367 
    2368                                 // now clean the lists
    2369                                 while (!TouchedStack->IsEmpty()){
    2370                                         Walker = TouchedStack->PopFirst();
    2371                                         PredecessorList[Walker->nr] = NULL;
    2372                                         ShortestPathList[Walker->nr] = -1;
    2373                                         ColorList[Walker->nr] = white;
    2374                                 }
    2375                         }
    2376                         *out << Verbose(1) << "Minimum ring size of " << *Root << " is " << MinimumRingSize[Root->GetTrueFather()->nr] << "." << endl;
    2377                 }
    2378                 *out << Verbose(1) << "Minimum ring size is " << MinRingSize << ", over " << NumCycles << " cycles total." << endl;
    2379         } else
    2380                 *out << Verbose(1) << "No rings were detected in the molecular structure." << endl;
    2381 
    2382         Free((void **)&PredecessorList, "molecule::CyclicStructureAnalysis: **PredecessorList");
    2383         Free((void **)&ShortestPathList, "molecule::CyclicStructureAnalysis: **ShortestPathList");
    2384         Free((void **)&ColorList, "molecule::CyclicStructureAnalysis: **ColorList");
    2385         delete(BFSStack);
     2254        } else {
     2255          *out << Verbose(2) << "Bond " << *Binder << " not Visiting, is the back edge." << endl;
     2256        }
     2257      }
     2258      ColorList[Walker->nr] = black;
     2259      *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
     2260      if (OtherAtom == Root) { // if we have found the root, check whether this cycle wasn't already found beforehand
     2261        // step through predecessor list
     2262        while (OtherAtom != BackEdge->rightatom) {
     2263          if (!OtherAtom->GetTrueFather()->IsCyclic)  // if one bond in the loop is not marked as cyclic, we haven't found this cycle yet
     2264            break;
     2265          else
     2266            OtherAtom = PredecessorList[OtherAtom->nr];
     2267        }
     2268        if (OtherAtom == BackEdge->rightatom) { // if each atom in found cycle is cyclic, loop's been found before already
     2269          *out << Verbose(3) << "This cycle was already found before, skipping and removing seeker from search." << endl;\
     2270          do {
     2271            OtherAtom = TouchedStack->PopLast();
     2272            if (PredecessorList[OtherAtom->nr] == Walker) {
     2273              *out << Verbose(4) << "Removing " << *OtherAtom << " from lists and stacks." << endl;
     2274              PredecessorList[OtherAtom->nr] = NULL;
     2275              ShortestPathList[OtherAtom->nr] = -1;
     2276              ColorList[OtherAtom->nr] = white;
     2277              BFSStack->RemoveItem(OtherAtom);
     2278            }
     2279          } while ((!TouchedStack->IsEmpty()) && (PredecessorList[OtherAtom->nr] == NULL));
     2280          TouchedStack->Push(OtherAtom);  // last was wrongly popped
     2281          OtherAtom = BackEdge->rightatom; // set to not Root
     2282        } else
     2283          OtherAtom = Root;
     2284      }
     2285    } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr])));
     2286
     2287    if (OtherAtom == Root) {
     2288      // now climb back the predecessor list and thus find the cycle members
     2289      NumCycles++;
     2290      RingSize = 1;
     2291      Root->GetTrueFather()->IsCyclic = true;
     2292      *out << Verbose(1) << "Found ring contains: ";
     2293      Walker = Root;
     2294      while (Walker != BackEdge->rightatom) {
     2295        *out << Walker->Name << " <-> ";
     2296        Walker = PredecessorList[Walker->nr];
     2297        Walker->GetTrueFather()->IsCyclic = true;
     2298        RingSize++;
     2299      }
     2300      *out << Walker->Name << "  with a length of " << RingSize << "." << endl << endl;
     2301      // walk through all and set MinimumRingSize
     2302      Walker = Root;
     2303      MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;
     2304      while (Walker != BackEdge->rightatom) {
     2305        Walker = PredecessorList[Walker->nr];
     2306        if (RingSize < MinimumRingSize[Walker->GetTrueFather()->nr])
     2307          MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;
     2308      }
     2309      if ((RingSize < MinRingSize) || (MinRingSize == -1))
     2310        MinRingSize = RingSize;
     2311    } else {
     2312      *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl;
     2313    }
     2314
     2315    // now clean the lists
     2316    while (!TouchedStack->IsEmpty()){
     2317      Walker = TouchedStack->PopFirst();
     2318      PredecessorList[Walker->nr] = NULL;
     2319      ShortestPathList[Walker->nr] = -1;
     2320      ColorList[Walker->nr] = white;
     2321    }
     2322  }
     2323  if (MinRingSize != -1) {
     2324    // go over all atoms
     2325    Root = start;
     2326    while(Root->next != end) {
     2327      Root = Root->next;
     2328
     2329      if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is
     2330        Walker = Root;
     2331        ShortestPathList[Walker->nr] = 0;
     2332        BFSStack->ClearStack();  // start with empty BFS stack
     2333        BFSStack->Push(Walker);
     2334        TouchedStack->Push(Walker);
     2335        //*out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;
     2336        OtherAtom = Walker;
     2337        while (OtherAtom != NULL) {  // look for Root
     2338          Walker = BFSStack->PopFirst();
     2339          //*out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;
     2340          for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
     2341            Binder = ListOfBondsPerAtom[Walker->nr][i];
     2342            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
     2343              OtherAtom = Binder->GetOtherAtom(Walker);
     2344              //*out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
     2345              if (ColorList[OtherAtom->nr] == white) {
     2346                TouchedStack->Push(OtherAtom);
     2347                ColorList[OtherAtom->nr] = lightgray;
     2348                PredecessorList[OtherAtom->nr] = Walker;  // Walker is the predecessor
     2349                ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
     2350                //*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;
     2351                if (OtherAtom->GetTrueFather()->IsCyclic) { // if the other atom is connected to a ring
     2352                  MinimumRingSize[Root->GetTrueFather()->nr] = ShortestPathList[OtherAtom->nr]+MinimumRingSize[OtherAtom->GetTrueFather()->nr];
     2353                  OtherAtom = NULL; //break;
     2354                  break;
     2355                } else
     2356                  BFSStack->Push(OtherAtom);
     2357              } else {
     2358                //*out << Verbose(3) << "Not Adding, has already been visited." << endl;
     2359              }
     2360            } else {
     2361              //*out << Verbose(3) << "Not Visiting, is a back edge." << endl;
     2362            }
     2363          }
     2364          ColorList[Walker->nr] = black;
     2365          //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
     2366        }
     2367
     2368        // now clean the lists
     2369        while (!TouchedStack->IsEmpty()){
     2370          Walker = TouchedStack->PopFirst();
     2371          PredecessorList[Walker->nr] = NULL;
     2372          ShortestPathList[Walker->nr] = -1;
     2373          ColorList[Walker->nr] = white;
     2374        }
     2375      }
     2376      *out << Verbose(1) << "Minimum ring size of " << *Root << " is " << MinimumRingSize[Root->GetTrueFather()->nr] << "." << endl;
     2377    }
     2378    *out << Verbose(1) << "Minimum ring size is " << MinRingSize << ", over " << NumCycles << " cycles total." << endl;
     2379  } else
     2380    *out << Verbose(1) << "No rings were detected in the molecular structure." << endl;
     2381
     2382  Free((void **)&PredecessorList, "molecule::CyclicStructureAnalysis: **PredecessorList");
     2383  Free((void **)&ShortestPathList, "molecule::CyclicStructureAnalysis: **ShortestPathList");
     2384  Free((void **)&ColorList, "molecule::CyclicStructureAnalysis: **ColorList");
     2385  delete(BFSStack);
    23862386};
    23872387
     
    23932393void molecule::SetNextComponentNumber(atom *vertex, int nr)
    23942394{
    2395         int i=0;
    2396         if (vertex != NULL) {
    2397                 for(;i<NumberOfBondsPerAtom[vertex->nr];i++) {
    2398                         if (vertex->ComponentNr[i] == -1) {      // check if not yet used
    2399                                 vertex->ComponentNr[i] = nr;
    2400                                 break;
    2401                         }
    2402                         else if (vertex->ComponentNr[i] == nr) // if number is already present, don't add another time
    2403                                 break;  // breaking here will not cause error!
    2404                 }
    2405                 if (i == NumberOfBondsPerAtom[vertex->nr])
    2406                         cerr << "Error: All Component entries are already occupied!" << endl;
    2407         } else
    2408                         cerr << "Error: Given vertex is NULL!" << endl;
     2395  int i=0;
     2396  if (vertex != NULL) {
     2397    for(;i<NumberOfBondsPerAtom[vertex->nr];i++) {
     2398      if (vertex->ComponentNr[i] == -1) {  // check if not yet used
     2399        vertex->ComponentNr[i] = nr;
     2400        break;
     2401      }
     2402      else if (vertex->ComponentNr[i] == nr) // if number is already present, don't add another time
     2403        break;  // breaking here will not cause error!
     2404    }
     2405    if (i == NumberOfBondsPerAtom[vertex->nr])
     2406      cerr << "Error: All Component entries are already occupied!" << endl;
     2407  } else
     2408      cerr << "Error: Given vertex is NULL!" << endl;
    24092409};
    24102410
     
    24142414void molecule::OutputComponentNumber(ofstream *out, atom *vertex)
    24152415{
    2416         for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)
    2417                 *out << vertex->ComponentNr[i] << "     ";
     2416  for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)
     2417    *out << vertex->ComponentNr[i] << "  ";
    24182418};
    24192419
     
    24222422void molecule::InitComponentNumbers()
    24232423{
    2424         atom *Walker = start;
    2425         while(Walker->next != end) {
    2426                 Walker = Walker->next;
    2427                 if (Walker->ComponentNr != NULL)
    2428                         Free((void **)&Walker->ComponentNr, "molecule::InitComponentNumbers: **Walker->ComponentNr");
    2429                 Walker->ComponentNr = (int *) Malloc(sizeof(int)*NumberOfBondsPerAtom[Walker->nr], "molecule::InitComponentNumbers: *Walker->ComponentNr");
    2430                 for (int i=NumberOfBondsPerAtom[Walker->nr];i--;)
    2431                         Walker->ComponentNr[i] = -1;
    2432         }
     2424  atom *Walker = start;
     2425  while(Walker->next != end) {
     2426    Walker = Walker->next;
     2427    if (Walker->ComponentNr != NULL)
     2428      Free((void **)&Walker->ComponentNr, "molecule::InitComponentNumbers: **Walker->ComponentNr");
     2429    Walker->ComponentNr = (int *) Malloc(sizeof(int)*NumberOfBondsPerAtom[Walker->nr], "molecule::InitComponentNumbers: *Walker->ComponentNr");
     2430    for (int i=NumberOfBondsPerAtom[Walker->nr];i--;)
     2431      Walker->ComponentNr[i] = -1;
     2432  }
    24332433};
    24342434
     
    24392439bond * molecule::FindNextUnused(atom *vertex)
    24402440{
    2441         for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)
    2442                 if (ListOfBondsPerAtom[vertex->nr][i]->IsUsed() == white)
    2443                         return(ListOfBondsPerAtom[vertex->nr][i]);
    2444         return NULL;
     2441  for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)
     2442    if (ListOfBondsPerAtom[vertex->nr][i]->IsUsed() == white)
     2443      return(ListOfBondsPerAtom[vertex->nr][i]);
     2444  return NULL;
    24452445};
    24462446
     
    24502450void molecule::ResetAllBondsToUnused()
    24512451{
    2452         bond *Binder = first;
    2453         while (Binder->next != last) {
    2454                 Binder = Binder->next;
    2455                 Binder->ResetUsed();
    2456         }
     2452  bond *Binder = first;
     2453  while (Binder->next != last) {
     2454    Binder = Binder->next;
     2455    Binder->ResetUsed();
     2456  }
    24572457};
    24582458
     
    24612461void molecule::ResetAllAtomNumbers()
    24622462{
    2463         atom *Walker = start;
    2464         while (Walker->next != end) {
    2465                 Walker = Walker->next;
    2466                 Walker->GraphNr = -1;
    2467         }
     2463  atom *Walker = start;
     2464  while (Walker->next != end) {
     2465    Walker = Walker->next;
     2466    Walker->GraphNr  = -1;
     2467  }
    24682468};
    24692469
     
    24742474void OutputAlreadyVisited(ofstream *out, int *list)
    24752475{
    2476         *out << Verbose(4) << "Already Visited Bonds:\t";
    2477         for(int i=1;i<=list[0];i++) *out << Verbose(0) << list[i] << "  ";
    2478         *out << endl;
     2476  *out << Verbose(4) << "Already Visited Bonds:\t";
     2477  for(int i=1;i<=list[0];i++) *out << Verbose(0) << list[i] << "  ";
     2478  *out << endl;
    24792479};
    24802480
     
    24822482 * The upper limit is
    24832483 * \f[
    2484  *      n = N \cdot C^k
     2484 *  n = N \cdot C^k
    24852485 * \f]
    24862486 * where \f$C=2^c\f$ and c is the maximum bond degree over N number of atoms.
     
    24912491int molecule::GuesstimateFragmentCount(ofstream *out, int order)
    24922492{
    2493         int c = 0;
    2494         int FragmentCount;
    2495         // get maximum bond degree
    2496         atom *Walker = start;
    2497         while (Walker->next != end) {
    2498                 Walker = Walker->next;
    2499                 c = (NumberOfBondsPerAtom[Walker->nr] > c) ? NumberOfBondsPerAtom[Walker->nr] : c;
    2500         }
    2501         FragmentCount = NoNonHydrogen*(1 << (c*order));
    2502         *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl;
    2503         return FragmentCount;
     2493  int c = 0;
     2494  int FragmentCount;
     2495  // get maximum bond degree
     2496  atom *Walker = start;
     2497  while (Walker->next != end) {
     2498    Walker = Walker->next;
     2499    c = (NumberOfBondsPerAtom[Walker->nr] > c) ? NumberOfBondsPerAtom[Walker->nr] : c;
     2500  }
     2501  FragmentCount = NoNonHydrogen*(1 << (c*order));
     2502  *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl;
     2503  return FragmentCount;
    25042504};
    25052505
     
    25122512bool molecule::ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet)
    25132513{
    2514         stringstream line;
    2515         int AtomNr;
    2516         int status = 0;
    2517 
    2518         line.str(buffer);
    2519         while (!line.eof()) {
    2520                 line >> AtomNr;
    2521                 if ((AtomNr >= 0) && (AtomNr < AtomCount)) {
    2522                         CurrentSet.insert(AtomNr);      // insert at end, hence in same order as in file!
    2523                         status++;
    2524                 } // else it's "-1" or else and thus must not be added
    2525         }
    2526         *out << Verbose(1) << "The scanned KeySet is ";
    2527         for(KeySet::iterator runner = CurrentSet.begin(); runner != CurrentSet.end(); runner++) {
    2528                 *out << (*runner) << "\t";
    2529         }
    2530         *out << endl;
    2531         return (status != 0);
     2514  stringstream line;
     2515  int AtomNr;
     2516  int status = 0;
     2517
     2518  line.str(buffer);
     2519  while (!line.eof()) {
     2520    line >> AtomNr;
     2521    if ((AtomNr >= 0) && (AtomNr < AtomCount)) {
     2522      CurrentSet.insert(AtomNr);  // insert at end, hence in same order as in file!
     2523      status++;
     2524    } // else it's "-1" or else and thus must not be added
     2525  }
     2526  *out << Verbose(1) << "The scanned KeySet is ";
     2527  for(KeySet::iterator runner = CurrentSet.begin(); runner != CurrentSet.end(); runner++) {
     2528    *out << (*runner) << "\t";
     2529  }
     2530  *out << endl;
     2531  return (status != 0);
    25322532};
    25332533
     
    25442544bool molecule::ParseKeySetFile(ofstream *out, char *path, Graph *&FragmentList)
    25452545{
    2546         bool status = true;
    2547         ifstream InputFile;
    2548         stringstream line;
    2549         GraphTestPair testGraphInsert;
    2550         int NumberOfFragments = 0;
    2551         double TEFactor;
    2552         char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename");
    2553 
    2554         if (FragmentList == NULL) { // check list pointer
    2555                 FragmentList = new Graph;
    2556         }
    2557 
    2558         // 1st pass: open file and read
    2559         *out << Verbose(1) << "Parsing the KeySet file ... " << endl;
    2560         sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, KEYSETFILE);
    2561         InputFile.open(filename);
    2562         if (InputFile != NULL) {
    2563                 // each line represents a new fragment
    2564                 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - *buffer");
    2565                 // 1. parse keysets and insert into temp. graph
    2566                 while (!InputFile.eof()) {
    2567                         InputFile.getline(buffer, MAXSTRINGSIZE);
    2568                         KeySet CurrentSet;
    2569                         if ((strlen(buffer) > 0) && (ScanBufferIntoKeySet(out, buffer, CurrentSet))) {  // if at least one valid atom was added, write config
    2570                                 testGraphInsert = FragmentList->insert(GraphPair (CurrentSet,pair<int,double>(NumberOfFragments++,1))); // store fragment number and current factor
    2571                                 if (!testGraphInsert.second) {
    2572                                         cerr << "KeySet file must be corrupt as there are two equal key sets therein!" << endl;
    2573                                 }
    2574                         }
    2575                 }
    2576                 // 2. Free and done
    2577                 InputFile.close();
    2578                 InputFile.clear();
    2579                 Free((void **)&buffer, "molecule::ParseKeySetFile - *buffer");
    2580                 *out << Verbose(1) << "done." << endl;
    2581         } else {
    2582                 *out << Verbose(1) << "File " << filename << " not found." << endl;
    2583                 status = false;
    2584         }
    2585 
    2586         // 2nd pass: open TEFactors file and read
    2587         *out << Verbose(1) << "Parsing the TEFactors file ... " << endl;
    2588         sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, TEFACTORSFILE);
    2589         InputFile.open(filename);
    2590         if (InputFile != NULL) {
    2591                 // 3. add found TEFactors to each keyset
    2592                 NumberOfFragments = 0;
    2593                 for(Graph::iterator runner = FragmentList->begin();runner != FragmentList->end(); runner++) {
    2594                         if (!InputFile.eof()) {
    2595                                 InputFile >> TEFactor;
    2596                                 (*runner).second.second = TEFactor;
    2597                                 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl;
    2598                         } else {
    2599                                 status = false;
    2600                                 break;
    2601                         }
    2602                 }
    2603                 // 4. Free and done
    2604                 InputFile.close();
    2605                 *out << Verbose(1) << "done." << endl;
    2606         } else {
    2607                 *out << Verbose(1) << "File " << filename << " not found." << endl;
    2608                 status = false;
    2609         }
    2610 
    2611         // free memory
    2612         Free((void **)&filename, "molecule::ParseKeySetFile - filename");
    2613 
    2614         return status;
     2546  bool status = true;
     2547  ifstream InputFile;
     2548  stringstream line;
     2549  GraphTestPair testGraphInsert;
     2550  int NumberOfFragments = 0;
     2551  double TEFactor;
     2552  char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename");
     2553
     2554  if (FragmentList == NULL) { // check list pointer
     2555    FragmentList = new Graph;
     2556  }
     2557
     2558  // 1st pass: open file and read
     2559  *out << Verbose(1) << "Parsing the KeySet file ... " << endl;
     2560  sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, KEYSETFILE);
     2561  InputFile.open(filename);
     2562  if (InputFile != NULL) {
     2563    // each line represents a new fragment
     2564    char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - *buffer");
     2565    // 1. parse keysets and insert into temp. graph
     2566    while (!InputFile.eof()) {
     2567      InputFile.getline(buffer, MAXSTRINGSIZE);
     2568      KeySet CurrentSet;
     2569      if ((strlen(buffer) > 0) && (ScanBufferIntoKeySet(out, buffer, CurrentSet))) {  // if at least one valid atom was added, write config
     2570        testGraphInsert = FragmentList->insert(GraphPair (CurrentSet,pair<int,double>(NumberOfFragments++,1)));  // store fragment number and current factor
     2571        if (!testGraphInsert.second) {
     2572          cerr << "KeySet file must be corrupt as there are two equal key sets therein!" << endl;
     2573        }
     2574      }
     2575    }
     2576    // 2. Free and done
     2577    InputFile.close();
     2578    InputFile.clear();
     2579    Free((void **)&buffer, "molecule::ParseKeySetFile - *buffer");
     2580    *out << Verbose(1) << "done." << endl;
     2581  } else {
     2582    *out << Verbose(1) << "File " << filename << " not found." << endl;
     2583    status = false;
     2584  }
     2585
     2586  // 2nd pass: open TEFactors file and read
     2587  *out << Verbose(1) << "Parsing the TEFactors file ... " << endl;
     2588  sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, TEFACTORSFILE);
     2589  InputFile.open(filename);
     2590  if (InputFile != NULL) {
     2591    // 3. add found TEFactors to each keyset
     2592    NumberOfFragments = 0;
     2593    for(Graph::iterator runner = FragmentList->begin();runner != FragmentList->end(); runner++) {
     2594      if (!InputFile.eof()) {
     2595        InputFile >> TEFactor;
     2596        (*runner).second.second = TEFactor;
     2597        *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl;
     2598      } else {
     2599        status = false;
     2600        break;
     2601      }
     2602    }
     2603    // 4. Free and done
     2604    InputFile.close();
     2605    *out << Verbose(1) << "done." << endl;
     2606  } else {
     2607    *out << Verbose(1) << "File " << filename << " not found." << endl;
     2608    status = false;
     2609  }
     2610
     2611  // free memory
     2612  Free((void **)&filename, "molecule::ParseKeySetFile - filename");
     2613
     2614  return status;
    26152615};
    26162616
     
    26232623bool molecule::StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path)
    26242624{
    2625         ofstream output;
    2626         bool status =   true;
    2627         string line;
    2628 
    2629         // open KeySet file
    2630         line = path;
    2631         line.append("/");
    2632         line += FRAGMENTPREFIX;
    2633         line += KEYSETFILE;
    2634         output.open(line.c_str(), ios::out);
    2635         *out << Verbose(1) << "Saving key sets of the total graph ... ";
    2636         if(output != NULL) {
    2637                 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) {
    2638                         for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) {
    2639                                 if (sprinter != (*runner).first.begin())
    2640                                         output << "\t";
    2641                                 output << *sprinter;
    2642                         }
    2643                         output << endl;
    2644                 }
    2645                 *out << "done." << endl;
    2646         } else {
    2647                 cerr << "Unable to open " << line << " for writing keysets!" << endl;
    2648                 status = false;
    2649         }
    2650         output.close();
    2651         output.clear();
    2652 
    2653         // open TEFactors file
    2654         line = path;
    2655         line.append("/");
    2656         line += FRAGMENTPREFIX;
    2657         line += TEFACTORSFILE;
    2658         output.open(line.c_str(), ios::out);
    2659         *out << Verbose(1) << "Saving TEFactors of the total graph ... ";
    2660         if(output != NULL) {
    2661                 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++)
    2662                         output << (*runner).second.second << endl;
    2663                 *out << Verbose(1) << "done." << endl;
    2664         } else {
    2665                 *out << Verbose(1) << "failed to open " << line << "." << endl;
    2666                 status = false;
    2667         }
    2668         output.close();
    2669 
    2670         return status;
     2625  ofstream output;
     2626  bool status =  true;
     2627  string line;
     2628
     2629  // open KeySet file
     2630  line = path;
     2631  line.append("/");
     2632  line += FRAGMENTPREFIX;
     2633  line += KEYSETFILE;
     2634  output.open(line.c_str(), ios::out);
     2635  *out << Verbose(1) << "Saving key sets of the total graph ... ";
     2636  if(output != NULL) {
     2637    for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) {
     2638      for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) {
     2639        if (sprinter != (*runner).first.begin())
     2640          output << "\t";
     2641        output << *sprinter;
     2642      }
     2643      output << endl;
     2644    }
     2645    *out << "done." << endl;
     2646  } else {
     2647    cerr << "Unable to open " << line << " for writing keysets!" << endl;
     2648    status = false;
     2649  }
     2650  output.close();
     2651  output.clear();
     2652
     2653  // open TEFactors file
     2654  line = path;
     2655  line.append("/");
     2656  line += FRAGMENTPREFIX;
     2657  line += TEFACTORSFILE;
     2658  output.open(line.c_str(), ios::out);
     2659  *out << Verbose(1) << "Saving TEFactors of the total graph ... ";
     2660  if(output != NULL) {
     2661    for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++)
     2662      output << (*runner).second.second << endl;
     2663    *out << Verbose(1) << "done." << endl;
     2664  } else {
     2665    *out << Verbose(1) << "failed to open " << line << "." << endl;
     2666    status = false;
     2667  }
     2668  output.close();
     2669
     2670  return status;
    26712671};
    26722672
     
    26792679bool molecule::StoreAdjacencyToFile(ofstream *out, char *path)
    26802680{
    2681         ofstream AdjacencyFile;
    2682         atom *Walker = NULL;
    2683         stringstream line;
    2684         bool status = true;
    2685 
    2686         line << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;
    2687         AdjacencyFile.open(line.str().c_str(), ios::out);
    2688         *out << Verbose(1) << "Saving adjacency list ... ";
    2689         if (AdjacencyFile != NULL) {
    2690                 Walker = start;
    2691                 while(Walker->next != end) {
    2692                         Walker = Walker->next;
    2693                         AdjacencyFile << Walker->nr << "\t";
    2694                         for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++)
    2695                                 AdjacencyFile << ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker)->nr << "\t";
    2696                         AdjacencyFile << endl;
    2697                 }
    2698                 AdjacencyFile.close();
    2699                 *out << Verbose(1) << "done." << endl;
    2700         } else {
    2701                 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;
    2702                 status = false;
    2703         }
    2704 
    2705         return status;
     2681  ofstream AdjacencyFile;
     2682  atom *Walker = NULL;
     2683  stringstream line;
     2684  bool status = true;
     2685
     2686  line << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;
     2687  AdjacencyFile.open(line.str().c_str(), ios::out);
     2688  *out << Verbose(1) << "Saving adjacency list ... ";
     2689  if (AdjacencyFile != NULL) {
     2690    Walker = start;
     2691    while(Walker->next != end) {
     2692      Walker = Walker->next;
     2693      AdjacencyFile << Walker->nr << "\t";
     2694      for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++)
     2695        AdjacencyFile << ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker)->nr << "\t";
     2696      AdjacencyFile << endl;
     2697    }
     2698    AdjacencyFile.close();
     2699    *out << Verbose(1) << "done." << endl;
     2700  } else {
     2701    *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;
     2702    status = false;
     2703  }
     2704
     2705  return status;
    27062706};
    27072707
     
    27142714bool molecule::CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms)
    27152715{
    2716         ifstream File;
    2717         stringstream filename;
    2718         bool status = true;
    2719         char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");
    2720 
    2721         filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;
    2722         File.open(filename.str().c_str(), ios::out);
    2723         *out << Verbose(1) << "Looking at bond structure stored in adjacency file and comparing to present one ... ";
    2724         if (File != NULL) {
    2725                 // allocate storage structure
    2726                 int NonMatchNumber = 0; // will number of atoms with differing bond structure
    2727                 int *CurrentBonds = (int *) Malloc(sizeof(int)*8, "molecule::CheckAdjacencyFileAgainstMolecule - CurrentBonds"); // contains parsed bonds of current atom
    2728                 int CurrentBondsOfAtom;
    2729 
    2730                 // Parse the file line by line and count the bonds
    2731                 while (!File.eof()) {
    2732                         File.getline(buffer, MAXSTRINGSIZE);
    2733                         stringstream line;
    2734                         line.str(buffer);
    2735                         int AtomNr = -1;
    2736                         line >> AtomNr;
    2737                         CurrentBondsOfAtom = -1; // we count one too far due to line end
    2738                         // parse into structure
    2739                         if ((AtomNr >= 0) && (AtomNr < AtomCount)) {
    2740                                 while (!line.eof())
    2741                                         line >> CurrentBonds[ ++CurrentBondsOfAtom ];
    2742                                 // compare against present bonds
    2743                                 //cout << Verbose(2) << "Walker is " << *Walker << ", bond partners: ";
    2744                                 if (CurrentBondsOfAtom == NumberOfBondsPerAtom[AtomNr]) {
    2745                                         for(int i=0;i<NumberOfBondsPerAtom[AtomNr];i++) {
    2746                                                 int id = ListOfBondsPerAtom[AtomNr][i]->GetOtherAtom(ListOfAtoms[AtomNr])->nr;
    2747                                                 int j = 0;
    2748                                                 for (;(j<CurrentBondsOfAtom) && (CurrentBonds[j++] != id);); // check against all parsed bonds
    2749                                                 if (CurrentBonds[j-1] != id) { // no match ? Then mark in ListOfAtoms
    2750                                                         ListOfAtoms[AtomNr] = NULL;
    2751                                                         NonMatchNumber++;
    2752                                                         status = false;
    2753                                                         //out << "[" << id << "]\t";
    2754                                                 } else {
    2755                                                         //out << id << "\t";
    2756                                                 }
    2757                                         }
    2758                                         //out << endl;
    2759                                 } else {
    2760                                         *out << "Number of bonds for Atom " << *ListOfAtoms[AtomNr] << " does not match, parsed " << CurrentBondsOfAtom << " against " << NumberOfBondsPerAtom[AtomNr] << "." << endl;
    2761                                         status = false;
    2762                                 }
    2763                         }
    2764                 }
    2765                 File.close();
    2766                 File.clear();
    2767                 if (status) { // if equal we parse the KeySetFile
    2768                         *out << Verbose(1) << "done: Equal." << endl;
    2769                         status = true;
    2770                 } else
    2771                         *out << Verbose(1) << "done: Not equal by " << NonMatchNumber << " atoms." << endl;
    2772                 Free((void **)&CurrentBonds, "molecule::CheckAdjacencyFileAgainstMolecule - **CurrentBonds");
    2773         } else {
    2774                 *out << Verbose(1) << "Adjacency file not found." << endl;
    2775                 status = false;
    2776         }
    2777         *out << endl;
    2778         Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");
    2779 
    2780         return status;
     2716  ifstream File;
     2717  stringstream filename;
     2718  bool status = true;
     2719  char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");
     2720
     2721  filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;
     2722  File.open(filename.str().c_str(), ios::out);
     2723  *out << Verbose(1) << "Looking at bond structure stored in adjacency file and comparing to present one ... ";
     2724  if (File != NULL) {
     2725    // allocate storage structure
     2726    int NonMatchNumber = 0;  // will number of atoms with differing bond structure
     2727    int *CurrentBonds = (int *) Malloc(sizeof(int)*8, "molecule::CheckAdjacencyFileAgainstMolecule - CurrentBonds"); // contains parsed bonds of current atom
     2728    int CurrentBondsOfAtom;
     2729
     2730    // Parse the file line by line and count the bonds
     2731    while (!File.eof()) {
     2732      File.getline(buffer, MAXSTRINGSIZE);
     2733      stringstream line;
     2734      line.str(buffer);
     2735      int AtomNr = -1;
     2736      line >> AtomNr;
     2737      CurrentBondsOfAtom = -1; // we count one too far due to line end
     2738      // parse into structure
     2739      if ((AtomNr >= 0) && (AtomNr < AtomCount)) {
     2740        while (!line.eof())
     2741          line >> CurrentBonds[ ++CurrentBondsOfAtom ];
     2742        // compare against present bonds
     2743        //cout << Verbose(2) << "Walker is " << *Walker << ", bond partners: ";
     2744        if (CurrentBondsOfAtom == NumberOfBondsPerAtom[AtomNr]) {
     2745          for(int i=0;i<NumberOfBondsPerAtom[AtomNr];i++) {
     2746            int id = ListOfBondsPerAtom[AtomNr][i]->GetOtherAtom(ListOfAtoms[AtomNr])->nr;
     2747            int j = 0;
     2748            for (;(j<CurrentBondsOfAtom) && (CurrentBonds[j++] != id);); // check against all parsed bonds
     2749            if (CurrentBonds[j-1] != id) { // no match ? Then mark in ListOfAtoms
     2750              ListOfAtoms[AtomNr] = NULL;
     2751              NonMatchNumber++;
     2752              status = false;
     2753              //out << "[" << id << "]\t";
     2754            } else {
     2755              //out << id << "\t";
     2756            }
     2757          }
     2758          //out << endl;
     2759        } else {
     2760          *out << "Number of bonds for Atom " << *ListOfAtoms[AtomNr] << " does not match, parsed " << CurrentBondsOfAtom << " against " << NumberOfBondsPerAtom[AtomNr] << "." << endl;
     2761          status = false;
     2762        }
     2763      }
     2764    }
     2765    File.close();
     2766    File.clear();
     2767    if (status) { // if equal we parse the KeySetFile
     2768      *out << Verbose(1) << "done: Equal." << endl;
     2769      status = true;
     2770    } else
     2771      *out << Verbose(1) << "done: Not equal by " << NonMatchNumber << " atoms." << endl;
     2772    Free((void **)&CurrentBonds, "molecule::CheckAdjacencyFileAgainstMolecule - **CurrentBonds");
     2773  } else {
     2774    *out << Verbose(1) << "Adjacency file not found." << endl;
     2775    status = false;
     2776  }
     2777  *out << endl;
     2778  Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");
     2779
     2780  return status;
    27812781};
    27822782
     
    27922792bool molecule::CheckOrderAtSite(ofstream *out, bool *AtomMask, Graph *GlobalKeySetList, int Order, int *MinimumRingSize, char *path)
    27932793{
    2794         atom *Walker = start;
    2795         bool status = false;
    2796         ifstream InputFile;
    2797 
    2798         // initialize mask list
    2799         for(int i=AtomCount;i--;)
    2800                 AtomMask[i] = false;
    2801 
    2802         if (Order < 0) { // adaptive increase of BondOrder per site
    2803                 if (AtomMask[AtomCount] == true)        // break after one step
    2804                         return false;
    2805                 // parse the EnergyPerFragment file
    2806                 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckOrderAtSite: *buffer");
    2807                 sprintf(buffer, "%s/%s%s.dat", path, FRAGMENTPREFIX, ENERGYPERFRAGMENT);
    2808                 InputFile.open(buffer, ios::in);
    2809                 if ((InputFile != NULL) && (GlobalKeySetList != NULL)) {
    2810                         // transmorph graph keyset list into indexed KeySetList
    2811                         map<int,KeySet> IndexKeySetList;
    2812                         for(Graph::iterator runner = GlobalKeySetList->begin(); runner != GlobalKeySetList->end(); runner++) {
    2813                                 IndexKeySetList.insert( pair<int,KeySet>(runner->second.first,runner->first) );
    2814                         }
    2815                         int lines = 0;
    2816                         // count the number of lines, i.e. the number of fragments
    2817                         InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines
    2818                         InputFile.getline(buffer, MAXSTRINGSIZE);
    2819                         while(!InputFile.eof()) {
    2820                                 InputFile.getline(buffer, MAXSTRINGSIZE);
    2821                                 lines++;
    2822                         }
    2823                         //*out << Verbose(2) << "Scanned " << lines-1 << " lines." << endl;      // one endline too much
    2824                         InputFile.clear();
    2825                         InputFile.seekg(ios::beg);
    2826                         map<int, pair<double,int> > AdaptiveCriteriaList;       // (Root No., (Value, Order)) !
    2827                         int No, FragOrder;
    2828                         double Value;
    2829                         // each line represents a fragment root (Atom::nr) id and its energy contribution
    2830                         InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines
    2831                         InputFile.getline(buffer, MAXSTRINGSIZE);
    2832                         while(!InputFile.eof()) {
    2833                                 InputFile.getline(buffer, MAXSTRINGSIZE);
    2834                                 if (strlen(buffer) > 2) {
    2835                                         //*out << Verbose(2) << "Scanning: " << buffer << endl;
    2836                                         stringstream line(buffer);
    2837                                         line >> FragOrder;
    2838                                         line >> ws >> No;
    2839                                         line >> ws >> Value; // skip time entry
    2840                                         line >> ws >> Value;
    2841                                         No -= 1;        // indices start at 1 in file, not 0
    2842                                         //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl;
    2843 
    2844                                         // clean the list of those entries that have been superceded by higher order terms already
    2845                                         map<int,KeySet>::iterator marker = IndexKeySetList.find(No);            // find keyset to Frag No.
    2846                                         if (marker != IndexKeySetList.end()) {  // if found
    2847                                                 Value *= 1 + MYEPSILON*(*((*marker).second.begin()));            // in case of equal energies this makes em not equal without changing anything actually
    2848                                                 // 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
    2849                                                 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) ));
    2850                                                 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first;
    2851                                                 if (!InsertedElement.second) { // this root is already present
    2852                                                         if ((*PresentItem).second.second < FragOrder)   // if order there is lower, update entry with higher-order term
    2853                                                                 //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)
    2854                                                                 {       // if value is smaller, update value and order
    2855                                                                 (*PresentItem).second.first = fabs(Value);
    2856                                                                 (*PresentItem).second.second = FragOrder;
    2857                                                                 *out << Verbose(2) << "Updated element (" <<    (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;
    2858                                                         } else {
    2859                                                                 *out << Verbose(2) << "Did not update element " <<      (*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl;
    2860                                                         }
    2861                                                 } else {
    2862                                                         *out << Verbose(2) << "Inserted element (" <<   (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;
    2863                                                 }
    2864                                         } else {
    2865                                                 *out << Verbose(1) << "No Fragment under No. " << No << "found." << endl;
    2866                                         }
    2867                                 }
    2868                         }
    2869                         // then map back onto (Value, (Root Nr., Order)) (i.e. sorted by value to pick the highest ones)
    2870                         map<double, pair<int,int> > FinalRootCandidates;
    2871                         *out << Verbose(1) << "Root candidate list is: " << endl;
    2872                         for(map<int, pair<double,int> >::iterator runner = AdaptiveCriteriaList.begin(); runner != AdaptiveCriteriaList.end(); runner++) {
    2873                                 Walker = FindAtom((*runner).first);
    2874                                 if (Walker != NULL) {
    2875                                         //if ((*runner).second.second >= Walker->AdaptiveOrder) { // only insert if this is an "active" root site for the current order
    2876                                         if (!Walker->MaxOrder) {
    2877                                                 *out << Verbose(2) << "(" << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "])" << endl;
    2878                                                 FinalRootCandidates.insert( make_pair( (*runner).second.first, pair<int,int>((*runner).first, (*runner).second.second) ) );
    2879                                         } else {
    2880                                                 *out << Verbose(2) << "Excluding (" << *Walker << ", " << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "]), as it has reached its maximum order." << endl;
    2881                                         }
    2882                                 } else {
    2883                                         cerr << "Atom No. " << (*runner).second.first << " was not found in this molecule." << endl;
    2884                                 }
    2885                         }
    2886                         // pick the ones still below threshold and mark as to be adaptively updated
    2887                         for(map<double, pair<int,int> >::iterator runner = FinalRootCandidates.upper_bound(pow(10.,Order)); runner != FinalRootCandidates.end(); runner++) {
    2888                                 No = (*runner).second.first;
    2889                                 Walker = FindAtom(No);
    2890                                 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) {
    2891                                         *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl;
    2892                                         AtomMask[No] = true;
    2893                                         status = true;
    2894                                 //} else
    2895                                         //*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;
    2896                         }
    2897                         // close and done
    2898                         InputFile.close();
    2899                         InputFile.clear();
    2900                 } else {
    2901                         cerr << "Unable to parse " << buffer << " file, incrementing all." << endl;
    2902                         while (Walker->next != end) {
    2903                                 Walker = Walker->next;
    2904                 #ifdef ADDHYDROGEN
    2905                                 if (Walker->type->Z != 1) // skip hydrogen
    2906                 #endif
    2907                                 {
    2908                                         AtomMask[Walker->nr] = true;    // include all (non-hydrogen) atoms
    2909                                         status = true;
    2910                                 }
    2911                         }
    2912                 }
    2913                 Free((void **)&buffer, "molecule::CheckOrderAtSite: *buffer");
    2914                 // pick a given number of highest values and set AtomMask
    2915         } else { // global increase of Bond Order
    2916                 while (Walker->next != end) {
    2917                         Walker = Walker->next;
    2918         #ifdef ADDHYDROGEN
    2919                         if (Walker->type->Z != 1) // skip hydrogen
    2920         #endif
    2921                         {
    2922                                 AtomMask[Walker->nr] = true;    // include all (non-hydrogen) atoms
    2923                                 if ((Order != 0) && (Walker->AdaptiveOrder < Order)) // && (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]))
    2924                                         status = true;
    2925                         }
    2926                 }
    2927                 if ((Order == 0) && (AtomMask[AtomCount] == false))     // single stepping, just check
    2928                         status = true;
    2929 
    2930                 if (!status) {
    2931                         if (Order == 0)
    2932                                 *out << Verbose(1) << "Single stepping done." << endl;
    2933                         else
    2934                                 *out << Verbose(1) << "Order at every site is already equal or above desired order " << Order << "." << endl;
    2935                 }
    2936         }
    2937 
    2938         // print atom mask for debugging
    2939         *out << "                                                       ";
    2940         for(int i=0;i<AtomCount;i++)
    2941                 *out << (i % 10);
    2942         *out << endl << "Atom mask is: ";
    2943         for(int i=0;i<AtomCount;i++)
    2944                 *out << (AtomMask[i] ? "t" : "f");
    2945         *out << endl;
    2946 
    2947         return status;
     2794  atom *Walker = start;
     2795  bool status = false;
     2796  ifstream InputFile;
     2797
     2798  // initialize mask list
     2799  for(int i=AtomCount;i--;)
     2800    AtomMask[i] = false;
     2801
     2802  if (Order < 0) { // adaptive increase of BondOrder per site
     2803    if (AtomMask[AtomCount] == true)  // break after one step
     2804      return false;
     2805    // parse the EnergyPerFragment file
     2806    char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckOrderAtSite: *buffer");
     2807    sprintf(buffer, "%s/%s%s.dat", path, FRAGMENTPREFIX, ENERGYPERFRAGMENT);
     2808    InputFile.open(buffer, ios::in);
     2809    if ((InputFile != NULL) && (GlobalKeySetList != NULL)) {
     2810      // transmorph graph keyset list into indexed KeySetList
     2811      map<int,KeySet> IndexKeySetList;
     2812      for(Graph::iterator runner = GlobalKeySetList->begin(); runner != GlobalKeySetList->end(); runner++) {
     2813        IndexKeySetList.insert( pair<int,KeySet>(runner->second.first,runner->first) );
     2814      }
     2815      int lines = 0;
     2816      // count the number of lines, i.e. the number of fragments
     2817      InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines
     2818      InputFile.getline(buffer, MAXSTRINGSIZE);
     2819      while(!InputFile.eof()) {
     2820        InputFile.getline(buffer, MAXSTRINGSIZE);
     2821        lines++;
     2822      }
     2823      //*out << Verbose(2) << "Scanned " << lines-1 << " lines." << endl;  // one endline too much
     2824      InputFile.clear();
     2825      InputFile.seekg(ios::beg);
     2826      map<int, pair<double,int> > AdaptiveCriteriaList;  // (Root No., (Value, Order)) !
     2827      int No, FragOrder;
     2828      double Value;
     2829      // each line represents a fragment root (Atom::nr) id and its energy contribution
     2830      InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines
     2831      InputFile.getline(buffer, MAXSTRINGSIZE);
     2832      while(!InputFile.eof()) {
     2833        InputFile.getline(buffer, MAXSTRINGSIZE);
     2834        if (strlen(buffer) > 2) {
     2835          //*out << Verbose(2) << "Scanning: " << buffer << endl;
     2836          stringstream line(buffer);
     2837          line >> FragOrder;
     2838          line >> ws >> No;
     2839          line >> ws >> Value; // skip time entry
     2840          line >> ws >> Value;
     2841          No -= 1;  // indices start at 1 in file, not 0
     2842          //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl;
     2843
     2844          // clean the list of those entries that have been superceded by higher order terms already
     2845          map<int,KeySet>::iterator marker = IndexKeySetList.find(No);    // find keyset to Frag No.
     2846          if (marker != IndexKeySetList.end()) {  // if found
     2847            Value *= 1 + MYEPSILON*(*((*marker).second.begin()));    // in case of equal energies this makes em not equal without changing anything actually
     2848            // 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
     2849            pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) ));
     2850            map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first;
     2851            if (!InsertedElement.second) { // this root is already present
     2852              if ((*PresentItem).second.second < FragOrder)  // if order there is lower, update entry with higher-order term
     2853                //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)
     2854                {  // if value is smaller, update value and order
     2855                (*PresentItem).second.first = fabs(Value);
     2856                (*PresentItem).second.second = FragOrder;
     2857                *out << Verbose(2) << "Updated element (" <<  (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;
     2858              } else {
     2859                *out << Verbose(2) << "Did not update element " <<  (*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl;
     2860              }
     2861            } else {
     2862              *out << Verbose(2) << "Inserted element (" <<  (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;
     2863            }
     2864          } else {
     2865            *out << Verbose(1) << "No Fragment under No. " << No << "found." << endl;
     2866          }
     2867        }
     2868      }
     2869      // then map back onto (Value, (Root Nr., Order)) (i.e. sorted by value to pick the highest ones)
     2870      map<double, pair<int,int> > FinalRootCandidates;
     2871      *out << Verbose(1) << "Root candidate list is: " << endl;
     2872      for(map<int, pair<double,int> >::iterator runner = AdaptiveCriteriaList.begin(); runner != AdaptiveCriteriaList.end(); runner++) {
     2873        Walker = FindAtom((*runner).first);
     2874        if (Walker != NULL) {
     2875          //if ((*runner).second.second >= Walker->AdaptiveOrder) { // only insert if this is an "active" root site for the current order
     2876          if (!Walker->MaxOrder) {
     2877            *out << Verbose(2) << "(" << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "])" << endl;
     2878            FinalRootCandidates.insert( make_pair( (*runner).second.first, pair<int,int>((*runner).first, (*runner).second.second) ) );
     2879          } else {
     2880            *out << Verbose(2) << "Excluding (" << *Walker << ", " << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "]), as it has reached its maximum order." << endl;
     2881          }
     2882        } else {
     2883          cerr << "Atom No. " << (*runner).second.first << " was not found in this molecule." << endl;
     2884        }
     2885      }
     2886      // pick the ones still below threshold and mark as to be adaptively updated
     2887      for(map<double, pair<int,int> >::iterator runner = FinalRootCandidates.upper_bound(pow(10.,Order)); runner != FinalRootCandidates.end(); runner++) {
     2888        No = (*runner).second.first;
     2889        Walker = FindAtom(No);
     2890        //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) {
     2891          *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl;
     2892          AtomMask[No] = true;
     2893          status = true;
     2894        //} else
     2895          //*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;
     2896      }
     2897      // close and done
     2898      InputFile.close();
     2899      InputFile.clear();
     2900    } else {
     2901      cerr << "Unable to parse " << buffer << " file, incrementing all." << endl;
     2902      while (Walker->next != end) {
     2903        Walker = Walker->next;
     2904    #ifdef ADDHYDROGEN
     2905        if (Walker->type->Z != 1) // skip hydrogen
     2906    #endif
     2907        {
     2908          AtomMask[Walker->nr] = true;  // include all (non-hydrogen) atoms
     2909          status = true;
     2910        }
     2911      }
     2912    }
     2913    Free((void **)&buffer, "molecule::CheckOrderAtSite: *buffer");
     2914    // pick a given number of highest values and set AtomMask
     2915  } else { // global increase of Bond Order
     2916    while (Walker->next != end) {
     2917      Walker = Walker->next;
     2918  #ifdef ADDHYDROGEN
     2919      if (Walker->type->Z != 1) // skip hydrogen
     2920  #endif
     2921      {
     2922        AtomMask[Walker->nr] = true;  // include all (non-hydrogen) atoms
     2923        if ((Order != 0) && (Walker->AdaptiveOrder < Order)) // && (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]))
     2924          status = true;
     2925      }
     2926    }
     2927    if ((Order == 0) && (AtomMask[AtomCount] == false))  // single stepping, just check
     2928      status = true;
     2929
     2930    if (!status) {
     2931      if (Order == 0)
     2932        *out << Verbose(1) << "Single stepping done." << endl;
     2933      else
     2934        *out << Verbose(1) << "Order at every site is already equal or above desired order " << Order << "." << endl;
     2935    }
     2936  }
     2937
     2938  // print atom mask for debugging
     2939  *out << "              ";
     2940  for(int i=0;i<AtomCount;i++)
     2941    *out << (i % 10);
     2942  *out << endl << "Atom mask is: ";
     2943  for(int i=0;i<AtomCount;i++)
     2944    *out << (AtomMask[i] ? "t" : "f");
     2945  *out << endl;
     2946
     2947  return status;
    29482948};
    29492949
     
    29552955bool molecule::CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex)
    29562956{
    2957         element *runner = elemente->start;
    2958         int AtomNo = 0;
    2959         atom *Walker = NULL;
    2960 
    2961         if (SortIndex != NULL) {
    2962                 *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl;
    2963                 return false;
    2964         }
    2965         SortIndex = (int *) Malloc(sizeof(int)*AtomCount, "molecule::FragmentMolecule: *SortIndex");
    2966         for(int i=AtomCount;i--;)
    2967                 SortIndex[i] = -1;
    2968         while (runner->next != elemente->end) { // go through every element
    2969                 runner = runner->next;
    2970                 if (ElementsInMolecule[runner->Z]) { // if this element got atoms
    2971                         Walker = start;
    2972                         while (Walker->next != end) { // go through every atom of this element
    2973                                 Walker = Walker->next;
    2974                                 if (Walker->type->Z == runner->Z) // if this atom fits to element
    2975                                         SortIndex[Walker->nr] = AtomNo++;
    2976                         }
    2977                 }
    2978         }
    2979         return true;
     2957  element *runner = elemente->start;
     2958  int AtomNo = 0;
     2959  atom *Walker = NULL;
     2960
     2961  if (SortIndex != NULL) {
     2962    *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl;
     2963    return false;
     2964  }
     2965  SortIndex = (int *) Malloc(sizeof(int)*AtomCount, "molecule::FragmentMolecule: *SortIndex");
     2966  for(int i=AtomCount;i--;)
     2967    SortIndex[i] = -1;
     2968  while (runner->next != elemente->end) { // go through every element
     2969    runner = runner->next;
     2970    if (ElementsInMolecule[runner->Z]) { // if this element got atoms
     2971      Walker = start;
     2972      while (Walker->next != end) { // go through every atom of this element
     2973        Walker = Walker->next;
     2974        if (Walker->type->Z == runner->Z) // if this atom fits to element
     2975          SortIndex[Walker->nr] = AtomNo++;
     2976      }
     2977    }
     2978  }
     2979  return true;
    29802980};
    29812981
     
    29862986y contribution", and that's why this consciously not done in the following loop)
    29872987 * -# in a loop over all subgraphs
    2988  *      -# calls FragmentBOSSANOVA with this RootStack and within the subgraph molecule structure
    2989  *      -# creates molecule (fragment)s from the returned keysets (StoreFragmentFromKeySet)
     2988 *  -# calls FragmentBOSSANOVA with this RootStack and within the subgraph molecule structure
     2989 *  -# creates molecule (fragment)s from the returned keysets (StoreFragmentFromKeySet)
    29902990 * -# combines the generated molecule lists from all subgraphs
    29912991 * -# saves to disk: fragment configs, adjacency, orderatsite, keyset files
     
    30003000int molecule::FragmentMolecule(ofstream *out, int Order, config *configuration)
    30013001{
    3002         MoleculeListClass *BondFragments = NULL;
    3003         int *SortIndex = NULL;
    3004         int *MinimumRingSize = new int[AtomCount];
    3005         int FragmentCounter;
    3006         MoleculeLeafClass *MolecularWalker = NULL;
    3007         MoleculeLeafClass *Subgraphs = NULL;                    // list of subgraphs from DFS analysis
    3008         fstream File;
    3009         bool FragmentationToDo = true;
    3010         class StackClass<bond *> *BackEdgeStack = NULL, *LocalBackEdgeStack = NULL;
    3011         bool CheckOrder = false;
    3012         Graph **FragmentList = NULL;
    3013         Graph *ParsedFragmentList = NULL;
    3014         Graph TotalGraph;                // graph with all keysets however local numbers
    3015         int TotalNumberOfKeySets = 0;
    3016         atom **ListOfAtoms = NULL;
    3017         atom ***ListOfLocalAtoms = NULL;
    3018         bool *AtomMask = NULL;
    3019 
    3020         *out << endl;
     3002  MoleculeListClass *BondFragments = NULL;
     3003  int *SortIndex = NULL;
     3004  int *MinimumRingSize = new int[AtomCount];
     3005  int FragmentCounter;
     3006  MoleculeLeafClass *MolecularWalker = NULL;
     3007  MoleculeLeafClass *Subgraphs = NULL;      // list of subgraphs from DFS analysis
     3008  fstream File;
     3009  bool FragmentationToDo = true;
     3010  class StackClass<bond *> *BackEdgeStack = NULL, *LocalBackEdgeStack = NULL;
     3011  bool CheckOrder = false;
     3012  Graph **FragmentList = NULL;
     3013  Graph *ParsedFragmentList = NULL;
     3014  Graph TotalGraph;    // graph with all keysets however local numbers
     3015  int TotalNumberOfKeySets = 0;
     3016  atom **ListOfAtoms = NULL;
     3017  atom ***ListOfLocalAtoms = NULL;
     3018  bool *AtomMask = NULL;
     3019
     3020  *out << endl;
    30213021#ifdef ADDHYDROGEN
    3022         *out << Verbose(0) << "I will treat hydrogen special and saturate dangling bonds with it." << endl;
     3022  *out << Verbose(0) << "I will treat hydrogen special and saturate dangling bonds with it." << endl;
    30233023#else
    3024         *out << Verbose(0) << "Hydrogen is treated just like the rest of the lot." << endl;
     3024  *out << Verbose(0) << "Hydrogen is treated just like the rest of the lot." << endl;
    30253025#endif
    30263026
    3027         // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++
    3028 
    3029         // ===== 1. Check whether bond structure is same as stored in files ====
    3030 
    3031         // fill the adjacency list
    3032         CreateListOfBondsPerAtom(out);
    3033 
    3034         // create lookup table for Atom::nr
    3035         FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount);
    3036 
    3037         // === compare it with adjacency file ===
    3038         FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms);
    3039         Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms");
    3040 
    3041         // ===== 2. perform a DFS analysis to gather info on cyclic structure and a list of disconnected subgraphs =====
    3042         Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack);
    3043         // fill the bond structure of the individually stored subgraphs
    3044         Subgraphs->next->FillBondStructureFromReference(out, this, (FragmentCounter = 0), ListOfLocalAtoms, false);     // we want to keep the created ListOfLocalAtoms
    3045         // analysis of the cycles (print rings, get minimum cycle length) for each subgraph
    3046         for(int i=AtomCount;i--;)
    3047                 MinimumRingSize[i] = AtomCount;
    3048         MolecularWalker = Subgraphs;
    3049         FragmentCounter = 0;
    3050         while (MolecularWalker->next != NULL) {
    3051                 MolecularWalker = MolecularWalker->next;
    3052                 LocalBackEdgeStack = new StackClass<bond *> (MolecularWalker->Leaf->BondCount);
    3053 //              // check the list of local atoms for debugging
    3054 //              *out << Verbose(0) << "ListOfLocalAtoms for this subgraph is:" << endl;
    3055 //              for (int i=0;i<AtomCount;i++)
    3056 //                      if (ListOfLocalAtoms[FragmentCounter][i] == NULL)
    3057 //                              *out << "\tNULL";
    3058 //                      else
    3059 //                              *out << "\t" << ListOfLocalAtoms[FragmentCounter][i]->Name;
    3060                 *out << Verbose(0) << "Gathering local back edges for subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;
    3061                 MolecularWalker->Leaf->PickLocalBackEdges(out, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack);
    3062                 *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;
    3063                 MolecularWalker->Leaf->CyclicStructureAnalysis(out, LocalBackEdgeStack, MinimumRingSize);
    3064                 *out << Verbose(0) << "Done with Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;
    3065                 delete(LocalBackEdgeStack);
    3066         }
    3067 
    3068         // ===== 3. if structure still valid, parse key set file and others =====
    3069         FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList);
    3070 
    3071         // ===== 4. check globally whether there's something to do actually (first adaptivity check)
    3072         FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath);
    3073 
    3074         // =================================== Begin of FRAGMENTATION ===============================
    3075         // ===== 6a. assign each keyset to its respective subgraph =====
    3076         Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true);
    3077 
    3078         // ===== 6b. prepare and go into the adaptive (Order<0), single-step (Order==0) or incremental (Order>0) cycle
    3079         KeyStack *RootStack = new KeyStack[Subgraphs->next->Count()];
    3080         AtomMask = new bool[AtomCount+1];
    3081         AtomMask[AtomCount] = false;
    3082         FragmentationToDo = false;      // if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards
    3083         while ((CheckOrder = CheckOrderAtSite(out, AtomMask, ParsedFragmentList, Order, MinimumRingSize, configuration->configpath))) {
    3084                 FragmentationToDo = FragmentationToDo || CheckOrder;
    3085                 AtomMask[AtomCount] = true;      // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite()
    3086                 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) =====
    3087                 Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0));
    3088 
    3089                 // ===== 7. fill the bond fragment list =====
    3090                 FragmentCounter = 0;
    3091                 MolecularWalker = Subgraphs;
    3092                 while (MolecularWalker->next != NULL) {
    3093                         MolecularWalker = MolecularWalker->next;
    3094                         *out << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl;
    3095                         //MolecularWalker->Leaf->OutputListOfBonds(out);        // output ListOfBondsPerAtom for debugging
    3096                         if (MolecularWalker->Leaf->first->next != MolecularWalker->Leaf->last) {
    3097                                 // call BOSSANOVA method
    3098                                 *out << Verbose(0) << endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= " << endl;
    3099                                 MolecularWalker->Leaf->FragmentBOSSANOVA(out, FragmentList[FragmentCounter], RootStack[FragmentCounter], MinimumRingSize);
    3100                         } else {
    3101                                 cerr << "Subgraph " << MolecularWalker << " has no atoms!" << endl;
    3102                         }
    3103                         FragmentCounter++;      // next fragment list
    3104                 }
    3105         }
    3106         delete[](RootStack);
    3107         delete[](AtomMask);
    3108         delete(ParsedFragmentList);
    3109         delete[](MinimumRingSize);
    3110 
    3111 
    3112         // ==================================== End of FRAGMENTATION ============================================
    3113 
    3114         // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf)
    3115         Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph);
    3116 
    3117         // free subgraph memory again
    3118         FragmentCounter = 0;
    3119         if (Subgraphs != NULL) {
    3120                 while (Subgraphs->next != NULL) {
    3121                         Subgraphs = Subgraphs->next;
    3122                         delete(FragmentList[FragmentCounter++]);
    3123                         delete(Subgraphs->previous);
    3124                 }
    3125                 delete(Subgraphs);
    3126         }
    3127         Free((void **)&FragmentList, "molecule::FragmentMolecule - **FragmentList");
    3128 
    3129         // ===== 8b. gather keyset lists (graphs) from all subgraphs and transform into MoleculeListClass =====
    3130         //if (FragmentationToDo) {              // we should always store the fragments again as coordination might have changed slightly without changing bond structure
    3131                 // allocate memory for the pointer array and transmorph graphs into full molecular fragments
    3132                 BondFragments = new MoleculeListClass();
    3133                 int k=0;
    3134                 for(Graph::iterator runner = TotalGraph.begin(); runner != TotalGraph.end(); runner++) {
    3135                         KeySet test = (*runner).first;
    3136                         *out << "Fragment No." << (*runner).second.first << " with TEFactor " << (*runner).second.second << "." << endl;
    3137                         BondFragments->insert(StoreFragmentFromKeySet(out, test, configuration));
    3138                         k++;
    3139                 }
    3140                 *out << k << "/" << BondFragments->ListOfMolecules.size() << " fragments generated from the keysets." << endl;
    3141 
    3142                 // ===== 9. Save fragments' configuration and keyset files et al to disk ===
    3143                 if (BondFragments->ListOfMolecules.size() != 0) {
    3144                         // create the SortIndex from BFS labels to order in the config file
    3145                         CreateMappingLabelsToConfigSequence(out, SortIndex);
    3146 
    3147                         *out << Verbose(1) << "Writing " << BondFragments->ListOfMolecules.size() << " possible bond fragmentation configs" << endl;
    3148                         if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex))
    3149                                 *out << Verbose(1) << "All configs written." << endl;
    3150                         else
    3151                                 *out << Verbose(1) << "Some config writing failed." << endl;
    3152 
    3153                         // store force index reference file
    3154                         BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex);
    3155 
    3156                         // store keysets file
    3157                         StoreKeySetFile(out, TotalGraph, configuration->configpath);
    3158 
    3159                         // store Adjacency file
    3160                         StoreAdjacencyToFile(out, configuration->configpath);
    3161 
    3162                         // store Hydrogen saturation correction file
    3163                         BondFragments->AddHydrogenCorrection(out, configuration->configpath);
    3164 
    3165                         // store adaptive orders into file
    3166                         StoreOrderAtSiteFile(out, configuration->configpath);
    3167 
    3168                         // restore orbital and Stop values
    3169                         CalculateOrbitals(*configuration);
    3170 
    3171                         // free memory for bond part
    3172                         *out << Verbose(1) << "Freeing bond memory" << endl;
    3173                         delete(FragmentList); // remove bond molecule from memory
    3174                         Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex");
    3175                 } else
    3176                         *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl;
    3177         //} else
    3178         //      *out << Verbose(1) << "No fragments to store." << endl;
    3179         *out << Verbose(0) << "End of bond fragmentation." << endl;
    3180 
    3181         return ((int)(!FragmentationToDo)+1);           // 1 - continue, 2 - stop (no fragmentation occured)
     3027  // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++
     3028
     3029  // ===== 1. Check whether bond structure is same as stored in files ====
     3030
     3031  // fill the adjacency list
     3032  CreateListOfBondsPerAtom(out);
     3033
     3034  // create lookup table for Atom::nr
     3035  FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount);
     3036
     3037  // === compare it with adjacency file ===
     3038  FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms);
     3039  Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms");
     3040
     3041  // ===== 2. perform a DFS analysis to gather info on cyclic structure and a list of disconnected subgraphs =====
     3042  Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack);
     3043  // fill the bond structure of the individually stored subgraphs
     3044  Subgraphs->next->FillBondStructureFromReference(out, this, (FragmentCounter = 0), ListOfLocalAtoms, false);  // we want to keep the created ListOfLocalAtoms
     3045  // analysis of the cycles (print rings, get minimum cycle length) for each subgraph
     3046  for(int i=AtomCount;i--;)
     3047    MinimumRingSize[i] = AtomCount;
     3048  MolecularWalker = Subgraphs;
     3049  FragmentCounter = 0;
     3050  while (MolecularWalker->next != NULL) {
     3051    MolecularWalker = MolecularWalker->next;
     3052    LocalBackEdgeStack = new StackClass<bond *> (MolecularWalker->Leaf->BondCount);
     3053//    // check the list of local atoms for debugging
     3054//    *out << Verbose(0) << "ListOfLocalAtoms for this subgraph is:" << endl;
     3055//    for (int i=0;i<AtomCount;i++)
     3056//      if (ListOfLocalAtoms[FragmentCounter][i] == NULL)
     3057//        *out << "\tNULL";
     3058//      else
     3059//        *out << "\t" << ListOfLocalAtoms[FragmentCounter][i]->Name;
     3060    *out << Verbose(0) << "Gathering local back edges for subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;
     3061    MolecularWalker->Leaf->PickLocalBackEdges(out, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack);
     3062    *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;
     3063    MolecularWalker->Leaf->CyclicStructureAnalysis(out, LocalBackEdgeStack, MinimumRingSize);
     3064    *out << Verbose(0) << "Done with Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;
     3065    delete(LocalBackEdgeStack);
     3066  }
     3067
     3068  // ===== 3. if structure still valid, parse key set file and others =====
     3069  FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList);
     3070
     3071  // ===== 4. check globally whether there's something to do actually (first adaptivity check)
     3072  FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath);
     3073
     3074  // =================================== Begin of FRAGMENTATION ===============================
     3075  // ===== 6a. assign each keyset to its respective subgraph =====
     3076  Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true);
     3077
     3078  // ===== 6b. prepare and go into the adaptive (Order<0), single-step (Order==0) or incremental (Order>0) cycle
     3079  KeyStack *RootStack = new KeyStack[Subgraphs->next->Count()];
     3080  AtomMask = new bool[AtomCount+1];
     3081  AtomMask[AtomCount] = false;
     3082  FragmentationToDo = false;  // if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards
     3083  while ((CheckOrder = CheckOrderAtSite(out, AtomMask, ParsedFragmentList, Order, MinimumRingSize, configuration->configpath))) {
     3084    FragmentationToDo = FragmentationToDo || CheckOrder;
     3085    AtomMask[AtomCount] = true;  // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite()
     3086    // ===== 6b. fill RootStack for each subgraph (second adaptivity check) =====
     3087    Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0));
     3088
     3089    // ===== 7. fill the bond fragment list =====
     3090    FragmentCounter = 0;
     3091    MolecularWalker = Subgraphs;
     3092    while (MolecularWalker->next != NULL) {
     3093      MolecularWalker = MolecularWalker->next;
     3094      *out << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl;
     3095      //MolecularWalker->Leaf->OutputListOfBonds(out);  // output ListOfBondsPerAtom for debugging
     3096      if (MolecularWalker->Leaf->first->next != MolecularWalker->Leaf->last) {
     3097        // call BOSSANOVA method
     3098        *out << Verbose(0) << endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= " << endl;
     3099        MolecularWalker->Leaf->FragmentBOSSANOVA(out, FragmentList[FragmentCounter], RootStack[FragmentCounter], MinimumRingSize);
     3100      } else {
     3101        cerr << "Subgraph " << MolecularWalker << " has no atoms!" << endl;
     3102      }
     3103      FragmentCounter++;  // next fragment list
     3104    }
     3105  }
     3106  delete[](RootStack);
     3107  delete[](AtomMask);
     3108  delete(ParsedFragmentList);
     3109  delete[](MinimumRingSize);
     3110
     3111
     3112  // ==================================== End of FRAGMENTATION ============================================
     3113
     3114  // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf)
     3115  Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph);
     3116
     3117  // free subgraph memory again
     3118  FragmentCounter = 0;
     3119  if (Subgraphs != NULL) {
     3120    while (Subgraphs->next != NULL) {
     3121      Subgraphs = Subgraphs->next;
     3122      delete(FragmentList[FragmentCounter++]);
     3123      delete(Subgraphs->previous);
     3124    }
     3125    delete(Subgraphs);
     3126  }
     3127  Free((void **)&FragmentList, "molecule::FragmentMolecule - **FragmentList");
     3128
     3129  // ===== 8b. gather keyset lists (graphs) from all subgraphs and transform into MoleculeListClass =====
     3130  //if (FragmentationToDo) {    // we should always store the fragments again as coordination might have changed slightly without changing bond structure
     3131    // allocate memory for the pointer array and transmorph graphs into full molecular fragments
     3132    BondFragments = new MoleculeListClass();
     3133    int k=0;
     3134    for(Graph::iterator runner = TotalGraph.begin(); runner != TotalGraph.end(); runner++) {
     3135      KeySet test = (*runner).first;
     3136      *out << "Fragment No." << (*runner).second.first << " with TEFactor " << (*runner).second.second << "." << endl;
     3137      BondFragments->insert(StoreFragmentFromKeySet(out, test, configuration));
     3138      k++;
     3139    }
     3140    *out << k << "/" << BondFragments->ListOfMolecules.size() << " fragments generated from the keysets." << endl;
     3141
     3142    // ===== 9. Save fragments' configuration and keyset files et al to disk ===
     3143    if (BondFragments->ListOfMolecules.size() != 0) {
     3144      // create the SortIndex from BFS labels to order in the config file
     3145      CreateMappingLabelsToConfigSequence(out, SortIndex);
     3146
     3147      *out << Verbose(1) << "Writing " << BondFragments->ListOfMolecules.size() << " possible bond fragmentation configs" << endl;
     3148      if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex))
     3149        *out << Verbose(1) << "All configs written." << endl;
     3150      else
     3151        *out << Verbose(1) << "Some config writing failed." << endl;
     3152
     3153      // store force index reference file
     3154      BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex);
     3155
     3156      // store keysets file
     3157      StoreKeySetFile(out, TotalGraph, configuration->configpath);
     3158
     3159      // store Adjacency file
     3160      StoreAdjacencyToFile(out, configuration->configpath);
     3161
     3162      // store Hydrogen saturation correction file
     3163      BondFragments->AddHydrogenCorrection(out, configuration->configpath);
     3164
     3165      // store adaptive orders into file
     3166      StoreOrderAtSiteFile(out, configuration->configpath);
     3167
     3168      // restore orbital and Stop values
     3169      CalculateOrbitals(*configuration);
     3170
     3171      // free memory for bond part
     3172      *out << Verbose(1) << "Freeing bond memory" << endl;
     3173      delete(FragmentList); // remove bond molecule from memory
     3174      Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex");
     3175    } else
     3176      *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl;
     3177  //} else
     3178  //  *out << Verbose(1) << "No fragments to store." << endl;
     3179  *out << Verbose(0) << "End of bond fragmentation." << endl;
     3180
     3181  return ((int)(!FragmentationToDo)+1);    // 1 - continue, 2 - stop (no fragmentation occured)
    31823182};
    31833183
     
    31923192bool molecule::PickLocalBackEdges(ofstream *out, atom **ListOfLocalAtoms, class StackClass<bond *> *&ReferenceStack, class StackClass<bond *> *&LocalStack)
    31933193{
    3194         bool status = true;
    3195         if (ReferenceStack->IsEmpty()) {
    3196                 cerr << "ReferenceStack is empty!" << endl;
    3197                 return false;
    3198         }
    3199         bond *Binder = ReferenceStack->PopFirst();
    3200         bond *FirstBond = Binder;        // mark the first bond, so that we don't loop through the stack indefinitely
    3201         atom *Walker = NULL, *OtherAtom = NULL;
    3202         ReferenceStack->Push(Binder);
    3203 
    3204         do {    // go through all bonds and push local ones
    3205                 Walker = ListOfLocalAtoms[Binder->leftatom->nr];        // get one atom in the reference molecule
    3206                 if (Walker != NULL) // if this Walker exists in the subgraph ...
    3207                         for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {           // go through the local list of bonds
    3208                                 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
    3209                                 if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond
    3210                                         LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]);
    3211                                         *out << Verbose(3) << "Found local edge " << *(ListOfBondsPerAtom[Walker->nr][i]) << "." << endl;
    3212                                         break;
    3213                                 }
    3214                         }
    3215                 Binder = ReferenceStack->PopFirst();    // loop the stack for next item
    3216                 *out << Verbose(3) << "Current candidate edge " << Binder << "." << endl;
    3217                 ReferenceStack->Push(Binder);
    3218         } while (FirstBond != Binder);
    3219 
    3220         return status;
     3194  bool status = true;
     3195  if (ReferenceStack->IsEmpty()) {
     3196    cerr << "ReferenceStack is empty!" << endl;
     3197    return false;
     3198  }
     3199  bond *Binder = ReferenceStack->PopFirst();
     3200  bond *FirstBond = Binder;  // mark the first bond, so that we don't loop through the stack indefinitely
     3201  atom *Walker = NULL, *OtherAtom = NULL;
     3202  ReferenceStack->Push(Binder);
     3203
     3204  do {  // go through all bonds and push local ones
     3205    Walker = ListOfLocalAtoms[Binder->leftatom->nr];  // get one atom in the reference molecule
     3206    if (Walker != NULL) // if this Walker exists in the subgraph ...
     3207      for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {    // go through the local list of bonds
     3208        OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
     3209        if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond
     3210          LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]);
     3211          *out << Verbose(3) << "Found local edge " << *(ListOfBondsPerAtom[Walker->nr][i]) << "." << endl;
     3212          break;
     3213        }
     3214      }
     3215    Binder = ReferenceStack->PopFirst();  // loop the stack for next item
     3216    *out << Verbose(3) << "Current candidate edge " << Binder << "." << endl;
     3217    ReferenceStack->Push(Binder);
     3218  } while (FirstBond != Binder);
     3219
     3220  return status;
    32213221};
    32223222
     
    32293229bool molecule::StoreOrderAtSiteFile(ofstream *out, char *path)
    32303230{
    3231         stringstream line;
    3232         ofstream file;
    3233 
    3234         line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE;
    3235         file.open(line.str().c_str());
    3236         *out << Verbose(1) << "Writing OrderAtSite " << ORDERATSITEFILE << " ... " << endl;
    3237         if (file != NULL) {
    3238                 atom *Walker = start;
    3239                 while (Walker->next != end) {
    3240                         Walker = Walker->next;
    3241                         file << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << endl;
    3242                         *out << Verbose(2) << "Storing: " << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << "." << endl;
    3243                 }
    3244                 file.close();
    3245                 *out << Verbose(1) << "done." << endl;
    3246                 return true;
    3247         } else {
    3248                 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;
    3249                 return false;
    3250         }
     3231  stringstream line;
     3232  ofstream file;
     3233
     3234  line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE;
     3235  file.open(line.str().c_str());
     3236  *out << Verbose(1) << "Writing OrderAtSite " << ORDERATSITEFILE << " ... " << endl;
     3237  if (file != NULL) {
     3238    atom *Walker = start;
     3239    while (Walker->next != end) {
     3240      Walker = Walker->next;
     3241      file << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << endl;
     3242      *out << Verbose(2) << "Storing: " << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << "." << endl;
     3243    }
     3244    file.close();
     3245    *out << Verbose(1) << "done." << endl;
     3246    return true;
     3247  } else {
     3248    *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;
     3249    return false;
     3250  }
    32513251};
    32523252
     
    32603260bool molecule::ParseOrderAtSiteFromFile(ofstream *out, char *path)
    32613261{
    3262         unsigned char *OrderArray = (unsigned char *) Malloc(sizeof(unsigned char)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *OrderArray");
    3263         bool *MaxArray = (bool *) Malloc(sizeof(bool)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *MaxArray");
    3264         bool status;
    3265         int AtomNr, value;
    3266         stringstream line;
    3267         ifstream file;
    3268 
    3269         *out << Verbose(1) << "Begin of ParseOrderAtSiteFromFile" << endl;
    3270         for(int i=AtomCount;i--;)
    3271                 OrderArray[i] = 0;
    3272         line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE;
    3273         file.open(line.str().c_str());
    3274         if (file != NULL) {
    3275                 for (int i=AtomCount;i--;) { // initialise with 0
    3276                         OrderArray[i] = 0;
    3277                         MaxArray[i] = 0;
    3278                 }
    3279                 while (!file.eof()) { // parse from file
    3280                         AtomNr = -1;
    3281                         file >> AtomNr;
    3282                         if (AtomNr != -1) {      // test whether we really parsed something (this is necessary, otherwise last atom is set twice and to 0 on second time)
    3283                                 file >> value;
    3284                                 OrderArray[AtomNr] = value;
    3285                                 file >> value;
    3286                                 MaxArray[AtomNr] = value;
    3287                                 //*out << Verbose(2) << "AtomNr " << AtomNr << " with order " << (int)OrderArray[AtomNr] << " and max order set to " << (int)MaxArray[AtomNr] << "." << endl;
    3288                         }
    3289                 }
    3290                 atom *Walker = start;
    3291                 while (Walker->next != end) { // fill into atom classes
    3292                         Walker = Walker->next;
    3293                         Walker->AdaptiveOrder = OrderArray[Walker->nr];
    3294                         Walker->MaxOrder = MaxArray[Walker->nr];
    3295                         *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl;
    3296                 }
    3297                 file.close();
    3298                 *out << Verbose(1) << "done." << endl;
    3299                 status = true;
    3300         } else {
    3301                 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;
    3302                 status = false;
    3303         }
    3304         Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray");
    3305         Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray");
    3306 
    3307         *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl;
    3308         return status;
     3262  unsigned char *OrderArray = (unsigned char *) Malloc(sizeof(unsigned char)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *OrderArray");
     3263  bool *MaxArray = (bool *) Malloc(sizeof(bool)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *MaxArray");
     3264  bool status;
     3265  int AtomNr, value;
     3266  stringstream line;
     3267  ifstream file;
     3268
     3269  *out << Verbose(1) << "Begin of ParseOrderAtSiteFromFile" << endl;
     3270  for(int i=AtomCount;i--;)
     3271    OrderArray[i] = 0;
     3272  line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE;
     3273  file.open(line.str().c_str());
     3274  if (file != NULL) {
     3275    for (int i=AtomCount;i--;) { // initialise with 0
     3276      OrderArray[i] = 0;
     3277      MaxArray[i] = 0;
     3278    }
     3279    while (!file.eof()) { // parse from file
     3280      AtomNr = -1;
     3281      file >> AtomNr;
     3282      if (AtomNr != -1) {  // test whether we really parsed something (this is necessary, otherwise last atom is set twice and to 0 on second time)
     3283        file >> value;
     3284        OrderArray[AtomNr] = value;
     3285        file >> value;
     3286        MaxArray[AtomNr] = value;
     3287        //*out << Verbose(2) << "AtomNr " << AtomNr << " with order " << (int)OrderArray[AtomNr] << " and max order set to " << (int)MaxArray[AtomNr] << "." << endl;
     3288      }
     3289    }
     3290    atom *Walker = start;
     3291    while (Walker->next != end) { // fill into atom classes
     3292      Walker = Walker->next;
     3293      Walker->AdaptiveOrder = OrderArray[Walker->nr];
     3294      Walker->MaxOrder = MaxArray[Walker->nr];
     3295      *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl;
     3296    }
     3297    file.close();
     3298    *out << Verbose(1) << "done." << endl;
     3299    status = true;
     3300  } else {
     3301    *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;
     3302    status = false;
     3303  }
     3304  Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray");
     3305  Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray");
     3306
     3307  *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl;
     3308  return status;
    33093309};
    33103310
     
    33173317void molecule::CreateListOfBondsPerAtom(ofstream *out)
    33183318{
    3319         bond *Binder = NULL;
    3320         atom *Walker = NULL;
    3321         int TotalDegree;
    3322         *out << Verbose(1) << "Begin of Creating ListOfBondsPerAtom: AtomCount = " << AtomCount << "\tBondCount = " << BondCount << "\tNoNonBonds = " << NoNonBonds << "." << endl;
    3323 
    3324         // re-allocate memory
    3325         *out << Verbose(2) << "(Re-)Allocating memory." << endl;
    3326         if (ListOfBondsPerAtom != NULL) {
    3327                 for(int i=AtomCount;i--;)
    3328                         Free((void **)&ListOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom[i]");
    3329                 Free((void **)&ListOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom");
    3330         }
    3331         if (NumberOfBondsPerAtom != NULL)
    3332                 Free((void **)&NumberOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: NumberOfBondsPerAtom");
    3333         ListOfBondsPerAtom = (bond ***) Malloc(sizeof(bond **)*AtomCount, "molecule::CreateListOfBondsPerAtom: ***ListOfBondsPerAtom");
    3334         NumberOfBondsPerAtom = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfBondsPerAtom: *NumberOfBondsPerAtom");
    3335 
    3336         // reset bond counts per atom
    3337         for(int i=AtomCount;i--;)
    3338                 NumberOfBondsPerAtom[i] = 0;
    3339         // count bonds per atom
    3340         Binder = first;
    3341         while (Binder->next != last) {
    3342                 Binder = Binder->next;
    3343                 NumberOfBondsPerAtom[Binder->leftatom->nr]++;
    3344                 NumberOfBondsPerAtom[Binder->rightatom->nr]++;
    3345         }
    3346         for(int i=AtomCount;i--;) {
    3347                 // allocate list of bonds per atom
    3348                 ListOfBondsPerAtom[i] = (bond **) Malloc(sizeof(bond *)*NumberOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: **ListOfBondsPerAtom[]");
    3349                 // clear the list again, now each NumberOfBondsPerAtom marks current free field
    3350                 NumberOfBondsPerAtom[i] = 0;
    3351         }
    3352         // fill the list
    3353         Binder = first;
    3354         while (Binder->next != last) {
    3355                 Binder = Binder->next;
    3356                 ListOfBondsPerAtom[Binder->leftatom->nr][NumberOfBondsPerAtom[Binder->leftatom->nr]++] = Binder;
    3357                 ListOfBondsPerAtom[Binder->rightatom->nr][NumberOfBondsPerAtom[Binder->rightatom->nr]++] = Binder;
    3358         }
    3359 
    3360         // output list for debugging
    3361         *out << Verbose(3) << "ListOfBondsPerAtom for each atom:" << endl;
    3362         Walker = start;
    3363         while (Walker->next != end) {
    3364                 Walker = Walker->next;
    3365                 *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: ";
    3366                 TotalDegree = 0;
    3367                 for (int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) {
    3368                         *out << *ListOfBondsPerAtom[Walker->nr][j] << "\t";
    3369                         TotalDegree += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;
    3370                 }
    3371                 *out << " -- TotalDegree: " << TotalDegree << endl;
    3372         }
    3373         *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl;
     3319  bond *Binder = NULL;
     3320  atom *Walker = NULL;
     3321  int TotalDegree;
     3322  *out << Verbose(1) << "Begin of Creating ListOfBondsPerAtom: AtomCount = " << AtomCount << "\tBondCount = " << BondCount << "\tNoNonBonds = " << NoNonBonds << "." << endl;
     3323
     3324  // re-allocate memory
     3325  *out << Verbose(2) << "(Re-)Allocating memory." << endl;
     3326  if (ListOfBondsPerAtom != NULL) {
     3327    for(int i=AtomCount;i--;)
     3328      Free((void **)&ListOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom[i]");
     3329    Free((void **)&ListOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom");
     3330  }
     3331  if (NumberOfBondsPerAtom != NULL)
     3332    Free((void **)&NumberOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: NumberOfBondsPerAtom");
     3333  ListOfBondsPerAtom = (bond ***) Malloc(sizeof(bond **)*AtomCount, "molecule::CreateListOfBondsPerAtom: ***ListOfBondsPerAtom");
     3334  NumberOfBondsPerAtom = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfBondsPerAtom: *NumberOfBondsPerAtom");
     3335
     3336  // reset bond counts per atom
     3337  for(int i=AtomCount;i--;)
     3338    NumberOfBondsPerAtom[i] = 0;
     3339  // count bonds per atom
     3340  Binder = first;
     3341  while (Binder->next != last) {
     3342    Binder = Binder->next;
     3343    NumberOfBondsPerAtom[Binder->leftatom->nr]++;
     3344    NumberOfBondsPerAtom[Binder->rightatom->nr]++;
     3345  }
     3346  for(int i=AtomCount;i--;) {
     3347    // allocate list of bonds per atom
     3348    ListOfBondsPerAtom[i] = (bond **) Malloc(sizeof(bond *)*NumberOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: **ListOfBondsPerAtom[]");
     3349    // clear the list again, now each NumberOfBondsPerAtom marks current free field
     3350    NumberOfBondsPerAtom[i] = 0;
     3351  }
     3352  // fill the list
     3353  Binder = first;
     3354  while (Binder->next != last) {
     3355    Binder = Binder->next;
     3356    ListOfBondsPerAtom[Binder->leftatom->nr][NumberOfBondsPerAtom[Binder->leftatom->nr]++] = Binder;
     3357    ListOfBondsPerAtom[Binder->rightatom->nr][NumberOfBondsPerAtom[Binder->rightatom->nr]++] = Binder;
     3358  }
     3359
     3360  // output list for debugging
     3361  *out << Verbose(3) << "ListOfBondsPerAtom for each atom:" << endl;
     3362  Walker = start;
     3363  while (Walker->next != end) {
     3364    Walker = Walker->next;
     3365    *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: ";
     3366    TotalDegree = 0;
     3367    for (int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) {
     3368      *out << *ListOfBondsPerAtom[Walker->nr][j] << "\t";
     3369      TotalDegree += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;
     3370    }
     3371    *out << " -- TotalDegree: " << TotalDegree << endl;
     3372  }
     3373  *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl;
    33743374};
    33753375
     
    33883388void molecule::BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem)
    33893389{
    3390         atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::BreadthFirstSearchAdd: **PredecessorList");
    3391         int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::BreadthFirstSearchAdd: *ShortestPathList");
    3392         enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::BreadthFirstSearchAdd: *ColorList");
    3393         class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);
    3394         atom *Walker = NULL, *OtherAtom = NULL;
    3395         bond *Binder = NULL;
    3396 
    3397         // add Root if not done yet
    3398         AtomStack->ClearStack();
    3399         if (AddedAtomList[Root->nr] == NULL)    // add Root if not yet present
    3400                 AddedAtomList[Root->nr] = Mol->AddCopyAtom(Root);
    3401         AtomStack->Push(Root);
    3402 
    3403         // initialise each vertex as white with no predecessor, empty queue, color Root lightgray
    3404         for (int i=AtomCount;i--;) {
    3405                 PredecessorList[i] = NULL;
    3406                 ShortestPathList[i] = -1;
    3407                 if (AddedAtomList[i] != NULL) // mark already present atoms (i.e. Root and maybe others) as visited
    3408                         ColorList[i] = lightgray;
    3409                 else
    3410                         ColorList[i] = white;
    3411         }
    3412         ShortestPathList[Root->nr] = 0;
    3413 
    3414         // and go on ... Queue always contains all lightgray vertices
    3415         while (!AtomStack->IsEmpty()) {
    3416                 // we have to pop the oldest atom from stack. This keeps the atoms on the stack always of the same ShortestPath distance.
    3417                 // 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
    3418                 // append length of 3 (their neighbours). Thus on stack we have always atoms of a certain length n at bottom of stack and
    3419                 // followed by n+1 till top of stack.
    3420                 Walker = AtomStack->PopFirst(); // pop oldest added
    3421                 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl;
    3422                 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
    3423                         Binder = ListOfBondsPerAtom[Walker->nr][i];
    3424                         if (Binder != NULL) { // don't look at bond equal NULL
    3425                                 OtherAtom = Binder->GetOtherAtom(Walker);
    3426                                 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
    3427                                 if (ColorList[OtherAtom->nr] == white) {
    3428                                         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)
    3429                                                 ColorList[OtherAtom->nr] = lightgray;
    3430                                         PredecessorList[OtherAtom->nr] = Walker;        // Walker is the predecessor
    3431                                         ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
    3432                                         *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;
    3433                                         if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance
    3434                                                 *out << Verbose(3);
    3435                                                 if (AddedAtomList[OtherAtom->nr] == NULL) { // add if it's not been so far
    3436                                                         AddedAtomList[OtherAtom->nr] = Mol->AddCopyAtom(OtherAtom);
    3437                                                         *out << "Added OtherAtom " << OtherAtom->Name;
    3438                                                         AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
    3439                                                         AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
    3440                                                         AddedBondList[Binder->nr]->Type = Binder->Type;
    3441                                                         *out << " and bond " << *(AddedBondList[Binder->nr]) << ", ";
    3442                                                 } 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)
    3443                                                         *out << "Not adding OtherAtom " << OtherAtom->Name;
    3444                                                         if (AddedBondList[Binder->nr] == NULL) {
    3445                                                                 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
    3446                                                                 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
    3447                                                                 AddedBondList[Binder->nr]->Type = Binder->Type;
    3448                                                                 *out << ", added Bond " << *(AddedBondList[Binder->nr]);
    3449                                                         } else
    3450                                                                 *out << ", not added Bond ";
    3451                                                 }
    3452                                                 *out << ", putting OtherAtom into queue." << endl;
    3453                                                 AtomStack->Push(OtherAtom);
    3454                                         } else { // out of bond order, then replace
    3455                                                 if ((AddedAtomList[OtherAtom->nr] == NULL) && (Binder->Cyclic))
    3456                                                         ColorList[OtherAtom->nr] = white; // unmark if it has not been queued/added, to make it available via its other bonds (cyclic)
    3457                                                 if (Binder == Bond)
    3458                                                         *out << Verbose(3) << "Not Queueing, is the Root bond";
    3459                                                 else if (ShortestPathList[OtherAtom->nr] >= BondOrder)
    3460                                                         *out << Verbose(3) << "Not Queueing, is out of Bond Count of " << BondOrder;
    3461                                                 if (!Binder->Cyclic)
    3462                                                         *out << ", is not part of a cyclic bond, saturating bond with Hydrogen." << endl;
    3463                                                 if (AddedBondList[Binder->nr] == NULL) {
    3464                                                         if ((AddedAtomList[OtherAtom->nr] != NULL)) { // .. whether we add or saturate
    3465                                                                 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
    3466                                                                 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
    3467                                                                 AddedBondList[Binder->nr]->Type = Binder->Type;
    3468                                                         } else {
     3390  atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::BreadthFirstSearchAdd: **PredecessorList");
     3391  int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::BreadthFirstSearchAdd: *ShortestPathList");
     3392  enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::BreadthFirstSearchAdd: *ColorList");
     3393  class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);
     3394  atom *Walker = NULL, *OtherAtom = NULL;
     3395  bond *Binder = NULL;
     3396
     3397  // add Root if not done yet
     3398  AtomStack->ClearStack();
     3399  if (AddedAtomList[Root->nr] == NULL)  // add Root if not yet present
     3400    AddedAtomList[Root->nr] = Mol->AddCopyAtom(Root);
     3401  AtomStack->Push(Root);
     3402
     3403  // initialise each vertex as white with no predecessor, empty queue, color Root lightgray
     3404  for (int i=AtomCount;i--;) {
     3405    PredecessorList[i] = NULL;
     3406    ShortestPathList[i] = -1;
     3407    if (AddedAtomList[i] != NULL) // mark already present atoms (i.e. Root and maybe others) as visited
     3408      ColorList[i] = lightgray;
     3409    else
     3410      ColorList[i] = white;
     3411  }
     3412  ShortestPathList[Root->nr] = 0;
     3413
     3414  // and go on ... Queue always contains all lightgray vertices
     3415  while (!AtomStack->IsEmpty()) {
     3416    // we have to pop the oldest atom from stack. This keeps the atoms on the stack always of the same ShortestPath distance.
     3417    // 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
     3418    // append length of 3 (their neighbours). Thus on stack we have always atoms of a certain length n at bottom of stack and
     3419    // followed by n+1 till top of stack.
     3420    Walker = AtomStack->PopFirst(); // pop oldest added
     3421    *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl;
     3422    for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
     3423      Binder = ListOfBondsPerAtom[Walker->nr][i];
     3424      if (Binder != NULL) { // don't look at bond equal NULL
     3425        OtherAtom = Binder->GetOtherAtom(Walker);
     3426        *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
     3427        if (ColorList[OtherAtom->nr] == white) {
     3428          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)
     3429            ColorList[OtherAtom->nr] = lightgray;
     3430          PredecessorList[OtherAtom->nr] = Walker;  // Walker is the predecessor
     3431          ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
     3432          *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;
     3433          if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance
     3434            *out << Verbose(3);
     3435            if (AddedAtomList[OtherAtom->nr] == NULL) { // add if it's not been so far
     3436              AddedAtomList[OtherAtom->nr] = Mol->AddCopyAtom(OtherAtom);
     3437              *out << "Added OtherAtom " << OtherAtom->Name;
     3438              AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
     3439              AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
     3440              AddedBondList[Binder->nr]->Type = Binder->Type;
     3441              *out << " and bond " << *(AddedBondList[Binder->nr]) << ", ";
     3442            } 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)
     3443              *out << "Not adding OtherAtom " << OtherAtom->Name;
     3444              if (AddedBondList[Binder->nr] == NULL) {
     3445                AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
     3446                AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
     3447                AddedBondList[Binder->nr]->Type = Binder->Type;
     3448                *out << ", added Bond " << *(AddedBondList[Binder->nr]);
     3449              } else
     3450                *out << ", not added Bond ";
     3451            }
     3452            *out << ", putting OtherAtom into queue." << endl;
     3453            AtomStack->Push(OtherAtom);
     3454          } else { // out of bond order, then replace
     3455            if ((AddedAtomList[OtherAtom->nr] == NULL) && (Binder->Cyclic))
     3456              ColorList[OtherAtom->nr] = white; // unmark if it has not been queued/added, to make it available via its other bonds (cyclic)
     3457            if (Binder == Bond)
     3458              *out << Verbose(3) << "Not Queueing, is the Root bond";
     3459            else if (ShortestPathList[OtherAtom->nr] >= BondOrder)
     3460              *out << Verbose(3) << "Not Queueing, is out of Bond Count of " << BondOrder;
     3461            if (!Binder->Cyclic)
     3462              *out << ", is not part of a cyclic bond, saturating bond with Hydrogen." << endl;
     3463            if (AddedBondList[Binder->nr] == NULL) {
     3464              if ((AddedAtomList[OtherAtom->nr] != NULL)) { // .. whether we add or saturate
     3465                AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
     3466                AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
     3467                AddedBondList[Binder->nr]->Type = Binder->Type;
     3468              } else {
    34693469#ifdef ADDHYDROGEN
    3470                                                                 if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))
    3471                                                                         exit(1);
     3470                if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))
     3471                  exit(1);
    34723472#endif
    3473                                                         }
    3474                                                 }
    3475                                         }
    3476                                 } else {
    3477                                         *out << Verbose(3) << "Not Adding, has already been visited." << endl;
    3478                                         // This has to be a cyclic bond, check whether it's present ...
    3479                                         if (AddedBondList[Binder->nr] == NULL) {
    3480                                                 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) {
    3481                                                         AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
    3482                                                         AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
    3483                                                         AddedBondList[Binder->nr]->Type = Binder->Type;
    3484                                                 } else { // if it's root bond it has to broken (otherwise we would not create the fragments)
     3473              }
     3474            }
     3475          }
     3476        } else {
     3477          *out << Verbose(3) << "Not Adding, has already been visited." << endl;
     3478          // This has to be a cyclic bond, check whether it's present ...
     3479          if (AddedBondList[Binder->nr] == NULL) {
     3480            if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) {
     3481              AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
     3482              AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
     3483              AddedBondList[Binder->nr]->Type = Binder->Type;
     3484            } else { // if it's root bond it has to broken (otherwise we would not create the fragments)
    34853485#ifdef ADDHYDROGEN
    3486                                                         if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))
    3487                                                                 exit(1);
     3486              if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))
     3487                exit(1);
    34883488#endif
    3489                                                 }
    3490                                         }
    3491                                 }
    3492                         }
    3493                 }
    3494                 ColorList[Walker->nr] = black;
    3495                 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
    3496         }
    3497         Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList");
    3498         Free((void **)&ShortestPathList, "molecule::BreadthFirstSearchAdd: **ShortestPathList");
    3499         Free((void **)&ColorList, "molecule::BreadthFirstSearchAdd: **ColorList");
    3500         delete(AtomStack);
     3489            }
     3490          }
     3491        }
     3492      }
     3493    }
     3494    ColorList[Walker->nr] = black;
     3495    *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
     3496  }
     3497  Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList");
     3498  Free((void **)&ShortestPathList, "molecule::BreadthFirstSearchAdd: **ShortestPathList");
     3499  Free((void **)&ColorList, "molecule::BreadthFirstSearchAdd: **ColorList");
     3500  delete(AtomStack);
    35013501};
    35023502
     
    35123512bool molecule::BuildInducedSubgraph(ofstream *out, const molecule *Father)
    35133513{
    3514         atom *Walker = NULL, *OtherAtom = NULL;
    3515         bool status = true;
    3516         atom **ParentList = (atom **) Malloc(sizeof(atom *)*Father->AtomCount, "molecule::BuildInducedSubgraph: **ParentList");
    3517 
    3518         *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl;
    3519 
    3520         // reset parent list
    3521         *out << Verbose(3) << "Resetting ParentList." << endl;
    3522         for (int i=Father->AtomCount;i--;)
    3523                 ParentList[i] = NULL;
    3524 
    3525         // fill parent list with sons
    3526         *out << Verbose(3) << "Filling Parent List." << endl;
    3527         Walker = start;
    3528         while (Walker->next != end) {
    3529                 Walker = Walker->next;
    3530                 ParentList[Walker->father->nr] = Walker;
    3531                 // Outputting List for debugging
    3532                 *out << Verbose(4) << "Son["<< Walker->father->nr <<"] of " << Walker->father <<        " is " << ParentList[Walker->father->nr] << "." << endl;
    3533         }
    3534 
    3535         // check each entry of parent list and if ok (one-to-and-onto matching) create bonds
    3536         *out << Verbose(3) << "Creating bonds." << endl;
    3537         Walker = Father->start;
    3538         while (Walker->next != Father->end) {
    3539                 Walker = Walker->next;
    3540                 if (ParentList[Walker->nr] != NULL) {
    3541                         if (ParentList[Walker->nr]->father != Walker) {
    3542                                 status = false;
    3543                         } else {
    3544                                 for (int i=0;i<Father->NumberOfBondsPerAtom[Walker->nr];i++) {
    3545                                         OtherAtom = Father->ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
    3546                                         if (ParentList[OtherAtom->nr] != NULL) { // if otheratom is also a father of an atom on this molecule, create the bond
    3547                                                 *out << Verbose(4) << "Endpoints of Bond " << Father->ListOfBondsPerAtom[Walker->nr][i] << " are both present: " << ParentList[Walker->nr]->Name << " and " << ParentList[OtherAtom->nr]->Name << "." << endl;
    3548                                                 AddBond(ParentList[Walker->nr], ParentList[OtherAtom->nr], Father->ListOfBondsPerAtom[Walker->nr][i]->BondDegree);
    3549                                         }
    3550                                 }
    3551                         }
    3552                 }
    3553         }
    3554 
    3555         Free((void **)&ParentList, "molecule::BuildInducedSubgraph: **ParentList");
    3556         *out << Verbose(2) << "End of BuildInducedSubgraph." << endl;
    3557         return status;
     3514  atom *Walker = NULL, *OtherAtom = NULL;
     3515  bool status = true;
     3516  atom **ParentList = (atom **) Malloc(sizeof(atom *)*Father->AtomCount, "molecule::BuildInducedSubgraph: **ParentList");
     3517
     3518  *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl;
     3519
     3520  // reset parent list
     3521  *out << Verbose(3) << "Resetting ParentList." << endl;
     3522  for (int i=Father->AtomCount;i--;)
     3523    ParentList[i] = NULL;
     3524
     3525  // fill parent list with sons
     3526  *out << Verbose(3) << "Filling Parent List." << endl;
     3527  Walker = start;
     3528  while (Walker->next != end) {
     3529    Walker = Walker->next;
     3530    ParentList[Walker->father->nr] = Walker;
     3531    // Outputting List for debugging
     3532    *out << Verbose(4) << "Son["<< Walker->father->nr <<"] of " << Walker->father <<  " is " << ParentList[Walker->father->nr] << "." << endl;
     3533  }
     3534
     3535  // check each entry of parent list and if ok (one-to-and-onto matching) create bonds
     3536  *out << Verbose(3) << "Creating bonds." << endl;
     3537  Walker = Father->start;
     3538  while (Walker->next != Father->end) {
     3539    Walker = Walker->next;
     3540    if (ParentList[Walker->nr] != NULL) {
     3541      if (ParentList[Walker->nr]->father != Walker) {
     3542        status = false;
     3543      } else {
     3544        for (int i=0;i<Father->NumberOfBondsPerAtom[Walker->nr];i++) {
     3545          OtherAtom = Father->ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
     3546          if (ParentList[OtherAtom->nr] != NULL) { // if otheratom is also a father of an atom on this molecule, create the bond
     3547            *out << Verbose(4) << "Endpoints of Bond " << Father->ListOfBondsPerAtom[Walker->nr][i] << " are both present: " << ParentList[Walker->nr]->Name << " and " << ParentList[OtherAtom->nr]->Name << "." << endl;
     3548            AddBond(ParentList[Walker->nr], ParentList[OtherAtom->nr], Father->ListOfBondsPerAtom[Walker->nr][i]->BondDegree);
     3549          }
     3550        }
     3551      }
     3552    }
     3553  }
     3554
     3555  Free((void **)&ParentList, "molecule::BuildInducedSubgraph: **ParentList");
     3556  *out << Verbose(2) << "End of BuildInducedSubgraph." << endl;
     3557  return status;
    35583558};
    35593559
     
    35673567int molecule::LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList)
    35683568{
    3569         atom *Runner = NULL;
    3570         int SP, Removal;
    3571 
    3572         *out << Verbose(2) << "Looking for removal candidate." << endl;
    3573         SP = -1; //0;   // not -1, so that Root is never removed
    3574         Removal = -1;
    3575         for (KeySet::iterator runner = Leaf->begin(); runner != Leaf->end(); runner++) {
    3576                 Runner = FindAtom((*runner));
    3577                 if (Runner->type->Z != 1) { // skip all those added hydrogens when re-filling snake stack
    3578                         if (ShortestPathList[(*runner)] > SP) { // remove the oldest one with longest shortest path
    3579                                 SP = ShortestPathList[(*runner)];
    3580                                 Removal = (*runner);
    3581                         }
    3582                 }
    3583         }
    3584         return Removal;
     3569  atom *Runner = NULL;
     3570  int SP, Removal;
     3571
     3572  *out << Verbose(2) << "Looking for removal candidate." << endl;
     3573  SP = -1; //0;  // not -1, so that Root is never removed
     3574  Removal = -1;
     3575  for (KeySet::iterator runner = Leaf->begin(); runner != Leaf->end(); runner++) {
     3576    Runner = FindAtom((*runner));
     3577    if (Runner->type->Z != 1) { // skip all those added hydrogens when re-filling snake stack
     3578      if (ShortestPathList[(*runner)] > SP) {  // remove the oldest one with longest shortest path
     3579        SP = ShortestPathList[(*runner)];
     3580        Removal = (*runner);
     3581      }
     3582    }
     3583  }
     3584  return Removal;
    35853585};
    35863586
     
    35953595molecule * molecule::StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem)
    35963596{
    3597         atom *Runner = NULL, *FatherOfRunner = NULL, *OtherFather = NULL;
    3598         atom **SonList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::StoreFragmentFromStack: **SonList");
    3599         molecule *Leaf = new molecule(elemente);
    3600         bool LonelyFlag = false;
    3601         int size;
    3602 
    3603 //      *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl;
    3604 
    3605         Leaf->BondDistance = BondDistance;
    3606         for(int i=NDIM*2;i--;)
    3607                 Leaf->cell_size[i] = cell_size[i];
    3608 
    3609         // initialise SonList (indicates when we need to replace a bond with hydrogen instead)
    3610         for(int i=AtomCount;i--;)
    3611                 SonList[i] = NULL;
    3612 
    3613         // first create the minimal set of atoms from the KeySet
    3614         size = 0;
    3615         for(KeySet::iterator runner = Leaflet.begin(); runner != Leaflet.end(); runner++) {
    3616                 FatherOfRunner = FindAtom((*runner));   // find the id
    3617                 SonList[FatherOfRunner->nr] = Leaf->AddCopyAtom(FatherOfRunner);
    3618                 size++;
    3619         }
    3620 
    3621         // create the bonds between all: Make it an induced subgraph and add hydrogen
    3622 //      *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl;
    3623         Runner = Leaf->start;
    3624         while (Runner->next != Leaf->end) {
    3625                 Runner = Runner->next;
    3626                 LonelyFlag = true;
    3627                 FatherOfRunner = Runner->father;
    3628                 if (SonList[FatherOfRunner->nr] != NULL)        {       // check if this, our father, is present in list
    3629                         // create all bonds
    3630                         for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father
    3631                                 OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner);
    3632 //                              *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather;
    3633                                 if (SonList[OtherFather->nr] != NULL) {
    3634 //                                      *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl;
    3635                                         if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba)
    3636 //                                              *out << Verbose(3) << "Adding Bond: ";
    3637 //                                              *out <<
    3638                                                 Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree);
    3639 //                                              *out << "." << endl;
    3640                                                 //NumBonds[Runner->nr]++;
    3641                                         } else {
    3642 //                                              *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl;
    3643                                         }
    3644                                         LonelyFlag = false;
    3645                                 } else {
    3646 //                                      *out << ", who has no son in this fragment molecule." << endl;
     3597  atom *Runner = NULL, *FatherOfRunner = NULL, *OtherFather = NULL;
     3598  atom **SonList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::StoreFragmentFromStack: **SonList");
     3599  molecule *Leaf = new molecule(elemente);
     3600  bool LonelyFlag = false;
     3601  int size;
     3602
     3603//  *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl;
     3604
     3605  Leaf->BondDistance = BondDistance;
     3606  for(int i=NDIM*2;i--;)
     3607    Leaf->cell_size[i] = cell_size[i];
     3608
     3609  // initialise SonList (indicates when we need to replace a bond with hydrogen instead)
     3610  for(int i=AtomCount;i--;)
     3611    SonList[i] = NULL;
     3612
     3613  // first create the minimal set of atoms from the KeySet
     3614  size = 0;
     3615  for(KeySet::iterator runner = Leaflet.begin(); runner != Leaflet.end(); runner++) {
     3616    FatherOfRunner = FindAtom((*runner));  // find the id
     3617    SonList[FatherOfRunner->nr] = Leaf->AddCopyAtom(FatherOfRunner);
     3618    size++;
     3619  }
     3620
     3621  // create the bonds between all: Make it an induced subgraph and add hydrogen
     3622//  *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl;
     3623  Runner = Leaf->start;
     3624  while (Runner->next != Leaf->end) {
     3625    Runner = Runner->next;
     3626    LonelyFlag = true;
     3627    FatherOfRunner = Runner->father;
     3628    if (SonList[FatherOfRunner->nr] != NULL)  {  // check if this, our father, is present in list
     3629      // create all bonds
     3630      for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father
     3631        OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner);
     3632//        *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather;
     3633        if (SonList[OtherFather->nr] != NULL) {
     3634//          *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl;
     3635          if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba)
     3636//            *out << Verbose(3) << "Adding Bond: ";
     3637//            *out <<
     3638            Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree);
     3639//            *out << "." << endl;
     3640            //NumBonds[Runner->nr]++;
     3641          } else {
     3642//            *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl;
     3643          }
     3644          LonelyFlag = false;
     3645        } else {
     3646//          *out << ", who has no son in this fragment molecule." << endl;
    36473647#ifdef ADDHYDROGEN
    3648                                         //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl;
    3649                                         if(!Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem))
    3650                                                 exit(1);
     3648          //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl;
     3649          if(!Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem))
     3650            exit(1);
    36513651#endif
    3652                                         //NumBonds[Runner->nr] += ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree;
    3653                                 }
    3654                         }
    3655                 } else {
    3656                         *out << Verbose(0) << "ERROR: Son " << Runner->Name << " has father " << FatherOfRunner->Name << " but its entry in SonList is " << SonList[FatherOfRunner->nr] << "!" << endl;
    3657                 }
    3658                 if ((LonelyFlag) && (size > 1)) {
    3659                         *out << Verbose(0) << *Runner << "has got bonds only to hydrogens!" << endl;
    3660                 }
     3652          //NumBonds[Runner->nr] += ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree;
     3653        }
     3654      }
     3655    } else {
     3656      *out << Verbose(0) << "ERROR: Son " << Runner->Name << " has father " << FatherOfRunner->Name << " but its entry in SonList is " << SonList[FatherOfRunner->nr] << "!" << endl;
     3657    }
     3658    if ((LonelyFlag) && (size > 1)) {
     3659      *out << Verbose(0) << *Runner << "has got bonds only to hydrogens!" << endl;
     3660    }
    36613661#ifdef ADDHYDROGEN
    3662                 while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen
    3663                         Runner = Runner->next;
     3662    while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen
     3663      Runner = Runner->next;
    36643664#endif
    3665         }
    3666         Leaf->CreateListOfBondsPerAtom(out);
    3667         //Leaflet->Leaf->ScanForPeriodicCorrection(out);
    3668         Free((void **)&SonList, "molecule::StoreFragmentFromStack: **SonList");
    3669 //      *out << Verbose(1) << "End of StoreFragmentFromKeyset." << endl;
    3670         return Leaf;
     3665  }
     3666  Leaf->CreateListOfBondsPerAtom(out);
     3667  //Leaflet->Leaf->ScanForPeriodicCorrection(out);
     3668  Free((void **)&SonList, "molecule::StoreFragmentFromStack: **SonList");
     3669//  *out << Verbose(1) << "End of StoreFragmentFromKeyset." << endl;
     3670  return Leaf;
    36713671};
    36723672
     
    36743674 */
    36753675struct UniqueFragments {
    3676         config *configuration;
    3677         atom *Root;
    3678         Graph *Leaflet;
    3679         KeySet *FragmentSet;
    3680         int ANOVAOrder;
    3681         int FragmentCounter;
    3682         int CurrentIndex;
    3683         double TEFactor;
    3684         int *ShortestPathList;
    3685         bool **UsedList;
    3686         bond **BondsPerSPList;
    3687         int *BondsPerSPCount;
     3676  config *configuration;
     3677  atom *Root;
     3678  Graph *Leaflet;
     3679  KeySet *FragmentSet;
     3680  int ANOVAOrder;
     3681  int FragmentCounter;
     3682  int CurrentIndex;
     3683  double TEFactor;
     3684  int *ShortestPathList;
     3685  bool **UsedList;
     3686  bond **BondsPerSPList;
     3687  int *BondsPerSPCount;
    36883688};
    36893689
    36903690/** From a given set of Bond sorted by Shortest Path distance, create all possible fragments of size \a SetDimension.
    36913691 * -# loops over every possible combination (2^dimension of edge set)
    3692  *      -# inserts current set, if there's still space left
    3693  *              -# yes: calls SPFragmentGenerator with structure, created new edge list and size respective to root dist
     3692 *  -# inserts current set, if there's still space left
     3693 *    -# yes: calls SPFragmentGenerator with structure, created new edge list and size respective to root dist
    36943694ance+1
    3695  *              -# no: stores fragment into keyset list by calling InsertFragmentIntoGraph
    3696  *      -# removes all items added into the snake stack (in UniqueFragments structure) added during level (root
     3695 *    -# no: stores fragment into keyset list by calling InsertFragmentIntoGraph
     3696 *  -# removes all items added into the snake stack (in UniqueFragments structure) added during level (root
    36973697distance) and current set
    36983698 * \param *out output stream for debugging
     
    37043704void molecule::SPFragmentGenerator(ofstream *out, struct UniqueFragments *FragmentSearch, int RootDistance, bond **BondsSet, int SetDimension, int SubOrder)
    37053705{
    3706         atom *OtherWalker = NULL;
    3707         int verbosity = 0; //FragmentSearch->ANOVAOrder-SubOrder;
    3708         int NumCombinations;
    3709         bool bit;
    3710         int bits, TouchedIndex, SubSetDimension, SP, Added;
    3711         int Removal;
    3712         int SpaceLeft;
    3713         int *TouchedList = (int *) Malloc(sizeof(int)*(SubOrder+1), "molecule::SPFragmentGenerator: *TouchedList");
    3714         bond *Binder = NULL;
    3715         bond **BondsList = NULL;
    3716         KeySetTestPair TestKeySetInsert;
    3717 
    3718         NumCombinations = 1 << SetDimension;
    3719 
    3720         // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen
    3721         // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder
    3722         // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden
    3723 
    3724         *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl;
    3725         *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;
    3726 
    3727         // initialised touched list (stores added atoms on this level)
    3728         *out << Verbose(1+verbosity) << "Clearing touched list." << endl;
    3729         for (TouchedIndex=SubOrder+1;TouchedIndex--;)   // empty touched list
    3730                 TouchedList[TouchedIndex] = -1;
    3731         TouchedIndex = 0;
    3732 
    3733         // create every possible combination of the endpieces
    3734         *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl;
    3735         for (int i=1;i<NumCombinations;i++) {   // sweep through all power set combinations (skip empty set!)
    3736                 // count the set bit of i
    3737                 bits = 0;
    3738                 for (int j=SetDimension;j--;)
    3739                         bits += (i & (1 << j)) >> j;
    3740 
    3741                 *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl;
    3742                 if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue
    3743                         // --1-- add this set of the power set of bond partners to the snake stack
    3744                         Added = 0;
    3745                         for (int j=0;j<SetDimension;j++) {      // pull out every bit by shifting
    3746                                 bit = ((i & (1 << j)) != 0);    // mask the bit for the j-th bond
    3747                                 if (bit) {      // if bit is set, we add this bond partner
    3748                                         OtherWalker = BondsSet[j]->rightatom;   // rightatom is always the one more distant, i.e. the one to add
    3749                                         //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl;
    3750                                         *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl;
    3751                                         TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr);
    3752                                         if (TestKeySetInsert.second) {
    3753                                                 TouchedList[TouchedIndex++] = OtherWalker->nr;  // note as added
    3754                                                 Added++;
    3755                                         } else {
    3756                                                 *out << Verbose(2+verbosity) << "This was item was already present in the keyset." << endl;
    3757                                         }
    3758                                                 //FragmentSearch->UsedList[OtherWalker->nr][i] = true;
    3759                                         //}
    3760                                 } else {
    3761                                         *out << Verbose(2+verbosity) << "Not adding." << endl;
    3762                                 }
    3763                         }
    3764 
    3765                         SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore
    3766                         if (SpaceLeft > 0) {
    3767                                 *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl;
    3768                                 if (SubOrder > 1) {             // Due to Added above we have to check extra whether we're not already reaching beyond the desired Order
    3769                                         // --2-- look at all added end pieces of this combination, construct bond subsets and sweep through a power set of these by recursion
    3770                                         SP = RootDistance+1;    // this is the next level
    3771                                         // first count the members in the subset
    3772                                         SubSetDimension = 0;
    3773                                         Binder = FragmentSearch->BondsPerSPList[2*SP];          // start node for this level
    3774                                         while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) {                // compare to end node of this level
    3775                                                 Binder = Binder->next;
    3776                                                 for (int k=TouchedIndex;k--;) {
    3777                                                         if (Binder->Contains(TouchedList[k]))    // if we added this very endpiece
    3778                                                                 SubSetDimension++;
    3779                                                 }
    3780                                         }
    3781                                         // then allocate and fill the list
    3782                                         BondsList = (bond **) Malloc(sizeof(bond *)*SubSetDimension, "molecule::SPFragmentGenerator: **BondsList");
    3783                                         SubSetDimension = 0;
    3784                                         Binder = FragmentSearch->BondsPerSPList[2*SP];
    3785                                         while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) {
    3786                                                 Binder = Binder->next;
    3787                                                 for (int k=0;k<TouchedIndex;k++) {
    3788                                                         if (Binder->leftatom->nr == TouchedList[k])      // leftatom is always the close one
    3789                                                                 BondsList[SubSetDimension++] = Binder;
    3790                                                 }
    3791                                         }
    3792                                         *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl;
    3793                                         SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits);
    3794                                         Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList");
    3795                                 }
    3796                         } else {
    3797                                 // --2-- otherwise store the complete fragment
    3798                                 *out << Verbose(1+verbosity) << "Enough items on stack for a fragment!" << endl;
    3799                                 // store fragment as a KeySet
    3800                                 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: ";
    3801                                 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++)
    3802                                         *out << (*runner) << " ";
    3803                                 *out << endl;
    3804                                 //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet))
    3805                                         //*out << Verbose(0) << "ERROR: The found fragment is not a connected subgraph!" << endl;
    3806                                 InsertFragmentIntoGraph(out, FragmentSearch);
    3807                                 //Removal = LookForRemovalCandidate(out, FragmentSearch->FragmentSet, FragmentSearch->ShortestPathList);
    3808                                 //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration);
    3809                         }
    3810 
    3811                         // --3-- remove all added items in this level from snake stack
    3812                         *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl;
    3813                         for(int j=0;j<TouchedIndex;j++) {
    3814                                 Removal = TouchedList[j];
    3815                                 *out << Verbose(2+verbosity) << "Removing item nr. " << Removal << " from snake stack." << endl;
    3816                                 FragmentSearch->FragmentSet->erase(Removal);
    3817                                 TouchedList[j] = -1;
    3818                         }
    3819                         *out << Verbose(2) << "Remaining local nr.s on snake stack are: ";
    3820                         for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++)
    3821                                 *out << (*runner) << " ";
    3822                         *out << endl;
    3823                         TouchedIndex = 0; // set Index to 0 for list of atoms added on this level
    3824                 } else {
    3825                         *out << Verbose(2+verbosity) << "More atoms to add for this set (" << bits << ") than space left on stack " << SubOrder << ", skipping this set." << endl;
    3826                 }
    3827         }
    3828         Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList");
    3829         *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl;
     3706  atom *OtherWalker = NULL;
     3707  int verbosity = 0; //FragmentSearch->ANOVAOrder-SubOrder;
     3708  int NumCombinations;
     3709  bool bit;
     3710  int bits, TouchedIndex, SubSetDimension, SP, Added;
     3711  int Removal;
     3712  int SpaceLeft;
     3713  int *TouchedList = (int *) Malloc(sizeof(int)*(SubOrder+1), "molecule::SPFragmentGenerator: *TouchedList");
     3714  bond *Binder = NULL;
     3715  bond **BondsList = NULL;
     3716  KeySetTestPair TestKeySetInsert;
     3717
     3718  NumCombinations = 1 << SetDimension;
     3719
     3720  // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen
     3721  // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder
     3722  // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden
     3723
     3724  *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl;
     3725  *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;
     3726
     3727  // initialised touched list (stores added atoms on this level)
     3728  *out << Verbose(1+verbosity) << "Clearing touched list." << endl;
     3729  for (TouchedIndex=SubOrder+1;TouchedIndex--;)  // empty touched list
     3730    TouchedList[TouchedIndex] = -1;
     3731  TouchedIndex = 0;
     3732
     3733  // create every possible combination of the endpieces
     3734  *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl;
     3735  for (int i=1;i<NumCombinations;i++) {  // sweep through all power set combinations (skip empty set!)
     3736    // count the set bit of i
     3737    bits = 0;
     3738    for (int j=SetDimension;j--;)
     3739      bits += (i & (1 << j)) >> j;
     3740
     3741    *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl;
     3742    if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue
     3743      // --1-- add this set of the power set of bond partners to the snake stack
     3744      Added = 0;
     3745      for (int j=0;j<SetDimension;j++) {  // pull out every bit by shifting
     3746        bit = ((i & (1 << j)) != 0);  // mask the bit for the j-th bond
     3747        if (bit) {  // if bit is set, we add this bond partner
     3748          OtherWalker = BondsSet[j]->rightatom;  // rightatom is always the one more distant, i.e. the one to add
     3749          //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl;
     3750          *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl;
     3751          TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr);
     3752          if (TestKeySetInsert.second) {
     3753            TouchedList[TouchedIndex++] = OtherWalker->nr;  // note as added
     3754            Added++;
     3755          } else {
     3756            *out << Verbose(2+verbosity) << "This was item was already present in the keyset." << endl;
     3757          }
     3758            //FragmentSearch->UsedList[OtherWalker->nr][i] = true;
     3759          //}
     3760        } else {
     3761          *out << Verbose(2+verbosity) << "Not adding." << endl;
     3762        }
     3763      }
     3764
     3765      SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore
     3766      if (SpaceLeft > 0) {
     3767        *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl;
     3768        if (SubOrder > 1) {    // Due to Added above we have to check extra whether we're not already reaching beyond the desired Order
     3769          // --2-- look at all added end pieces of this combination, construct bond subsets and sweep through a power set of these by recursion
     3770          SP = RootDistance+1;  // this is the next level
     3771          // first count the members in the subset
     3772          SubSetDimension = 0;
     3773          Binder = FragmentSearch->BondsPerSPList[2*SP];    // start node for this level
     3774          while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) {    // compare to end node of this level
     3775            Binder = Binder->next;
     3776            for (int k=TouchedIndex;k--;) {
     3777              if (Binder->Contains(TouchedList[k]))  // if we added this very endpiece
     3778                SubSetDimension++;
     3779            }
     3780          }
     3781          // then allocate and fill the list
     3782          BondsList = (bond **) Malloc(sizeof(bond *)*SubSetDimension, "molecule::SPFragmentGenerator: **BondsList");
     3783          SubSetDimension = 0;
     3784          Binder = FragmentSearch->BondsPerSPList[2*SP];
     3785          while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) {
     3786            Binder = Binder->next;
     3787            for (int k=0;k<TouchedIndex;k++) {
     3788              if (Binder->leftatom->nr == TouchedList[k])  // leftatom is always the close one
     3789                BondsList[SubSetDimension++] = Binder;
     3790            }
     3791          }
     3792          *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl;
     3793          SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits);
     3794          Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList");
     3795        }
     3796      } else {
     3797        // --2-- otherwise store the complete fragment
     3798        *out << Verbose(1+verbosity) << "Enough items on stack for a fragment!" << endl;
     3799        // store fragment as a KeySet
     3800        *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: ";
     3801        for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++)
     3802          *out << (*runner) << " ";
     3803        *out << endl;
     3804        //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet))
     3805          //*out << Verbose(0) << "ERROR: The found fragment is not a connected subgraph!" << endl;
     3806        InsertFragmentIntoGraph(out, FragmentSearch);
     3807        //Removal = LookForRemovalCandidate(out, FragmentSearch->FragmentSet, FragmentSearch->ShortestPathList);
     3808        //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration);
     3809      }
     3810
     3811      // --3-- remove all added items in this level from snake stack
     3812      *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl;
     3813      for(int j=0;j<TouchedIndex;j++) {
     3814        Removal = TouchedList[j];
     3815        *out << Verbose(2+verbosity) << "Removing item nr. " << Removal << " from snake stack." << endl;
     3816        FragmentSearch->FragmentSet->erase(Removal);
     3817        TouchedList[j] = -1;
     3818      }
     3819      *out << Verbose(2) << "Remaining local nr.s on snake stack are: ";
     3820      for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++)
     3821        *out << (*runner) << " ";
     3822      *out << endl;
     3823      TouchedIndex = 0; // set Index to 0 for list of atoms added on this level
     3824    } else {
     3825      *out << Verbose(2+verbosity) << "More atoms to add for this set (" << bits << ") than space left on stack " << SubOrder << ", skipping this set." << endl;
     3826    }
     3827  }
     3828  Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList");
     3829  *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl;
    38303830};
    38313831
     
    38383838bool molecule::CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment)
    38393839{
    3840         atom *Walker = NULL, *Walker2 = NULL;
    3841         bool BondStatus = false;
    3842         int size;
    3843 
    3844         *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl;
    3845         *out << Verbose(2) << "Disconnected atom: ";
    3846 
    3847         // count number of atoms in graph
    3848         size = 0;
    3849         for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++)
    3850                 size++;
    3851         if (size > 1)
    3852                 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) {
    3853                         Walker = FindAtom(*runner);
    3854                         BondStatus = false;
    3855                         for(KeySet::iterator runners = Fragment->begin(); runners != Fragment->end(); runners++) {
    3856                                 Walker2 = FindAtom(*runners);
    3857                                 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {
    3858                                         if (ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker) == Walker2) {
    3859                                                 BondStatus = true;
    3860                                                 break;
    3861                                         }
    3862                                         if (BondStatus)
    3863                                                 break;
    3864                                 }
    3865                         }
    3866                         if (!BondStatus) {
    3867                                 *out << (*Walker) << endl;
    3868                                 return false;
    3869                         }
    3870                 }
    3871         else {
    3872                 *out << "none." << endl;
    3873                 return true;
    3874         }
    3875         *out << "none." << endl;
    3876 
    3877         *out << Verbose(1) << "End of CheckForConnectedSubgraph" << endl;
    3878 
    3879         return true;
     3840  atom *Walker = NULL, *Walker2 = NULL;
     3841  bool BondStatus = false;
     3842  int size;
     3843
     3844  *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl;
     3845  *out << Verbose(2) << "Disconnected atom: ";
     3846
     3847  // count number of atoms in graph
     3848  size = 0;
     3849  for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++)
     3850    size++;
     3851  if (size > 1)
     3852    for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) {
     3853      Walker = FindAtom(*runner);
     3854      BondStatus = false;
     3855      for(KeySet::iterator runners = Fragment->begin(); runners != Fragment->end(); runners++) {
     3856        Walker2 = FindAtom(*runners);
     3857        for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {
     3858          if (ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker) == Walker2) {
     3859            BondStatus = true;
     3860            break;
     3861          }
     3862          if (BondStatus)
     3863            break;
     3864        }
     3865      }
     3866      if (!BondStatus) {
     3867        *out << (*Walker) << endl;
     3868        return false;
     3869      }
     3870    }
     3871  else {
     3872    *out << "none." << endl;
     3873    return true;
     3874  }
     3875  *out << "none." << endl;
     3876
     3877  *out << Verbose(1) << "End of CheckForConnectedSubgraph" << endl;
     3878
     3879  return true;
    38803880}
    38813881
     
    38973897int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet)
    38983898{
    3899         int SP, AtomKeyNr;
    3900         atom *Walker = NULL, *OtherWalker = NULL, *Predecessor = NULL;
    3901         bond *Binder = NULL;
    3902         bond *CurrentEdge = NULL;
    3903         bond **BondsList = NULL;
    3904         int RootKeyNr = FragmentSearch.Root->GetTrueFather()->nr;
    3905         int Counter = FragmentSearch.FragmentCounter;
    3906         int RemainingWalkers;
    3907 
    3908         *out << endl;
    3909         *out << Verbose(0) << "Begin of PowerSetGenerator with order " << Order << " at Root " << *FragmentSearch.Root << "." << endl;
    3910 
    3911         // prepare Label and SP arrays of the BFS search
    3912         FragmentSearch.ShortestPathList[FragmentSearch.Root->nr] = 0;
    3913 
    3914         // prepare root level (SP = 0) and a loop bond denoting Root
    3915         for (int i=1;i<Order;i++)
    3916                 FragmentSearch.BondsPerSPCount[i] = 0;
    3917         FragmentSearch.BondsPerSPCount[0] = 1;
    3918         Binder = new bond(FragmentSearch.Root, FragmentSearch.Root);
    3919         add(Binder, FragmentSearch.BondsPerSPList[1]);
    3920 
    3921         // do a BFS search to fill the SP lists and label the found vertices
    3922         // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into
    3923         // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning
    3924         // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth
    3925         // (EdgeinSPLevel) of this tree ...
    3926         // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence
    3927         // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction.
    3928         *out << endl;
    3929         *out << Verbose(0) << "Starting BFS analysis ..." << endl;
    3930         for (SP = 0; SP < (Order-1); SP++) {
    3931                 *out << Verbose(1) << "New SP level reached: " << SP << ", creating new SP list with " << FragmentSearch.BondsPerSPCount[SP] << " item(s)";
    3932                 if (SP > 0) {
    3933                         *out << ", old level closed with " << FragmentSearch.BondsPerSPCount[SP-1] << " item(s)." << endl;
    3934                         FragmentSearch.BondsPerSPCount[SP] = 0;
    3935                 } else
    3936                         *out << "." << endl;
    3937 
    3938                 RemainingWalkers = FragmentSearch.BondsPerSPCount[SP];
    3939                 CurrentEdge = FragmentSearch.BondsPerSPList[2*SP];              /// start of this SP level's list
    3940                 while (CurrentEdge->next != FragmentSearch.BondsPerSPList[2*SP+1]) {            /// end of this SP level's list
    3941                         CurrentEdge = CurrentEdge->next;
    3942                         RemainingWalkers--;
    3943                         Walker = CurrentEdge->rightatom;                // rightatom is always the one more distant
    3944                         Predecessor = CurrentEdge->leftatom;            // ... and leftatom is predecessor
    3945                         AtomKeyNr = Walker->nr;
    3946                         *out << Verbose(0) << "Current Walker is: " << *Walker << " with nr " << Walker->nr << " and SP of " << SP << ", with " << RemainingWalkers << " remaining walkers on this level." << endl;
    3947                         // check for new sp level
    3948                         // go through all its bonds
    3949                         *out << Verbose(1) << "Going through all bonds of Walker." << endl;
    3950                         for (int i=0;i<NumberOfBondsPerAtom[AtomKeyNr];i++) {
    3951                                 Binder = ListOfBondsPerAtom[AtomKeyNr][i];
    3952                                 OtherWalker = Binder->GetOtherAtom(Walker);
    3953                                 if ((RestrictedKeySet.find(OtherWalker->nr) != RestrictedKeySet.end())
    3954         #ifdef ADDHYDROGEN
    3955                                 && (OtherWalker->type->Z != 1)
    3956         #endif
    3957                                                                                                                                                                                                                                                         ) {     // skip hydrogens and restrict to fragment
    3958                                         *out << Verbose(2) << "Current partner is " << *OtherWalker << " with nr " << OtherWalker->nr << " in bond " << *Binder << "." << endl;
    3959                                         // set the label if not set (and push on root stack as well)
    3960                                         if ((OtherWalker != Predecessor) && (OtherWalker->GetTrueFather()->nr > RootKeyNr)) { // only pass through those with label bigger than Root's
    3961                                                 FragmentSearch.ShortestPathList[OtherWalker->nr] = SP+1;
    3962                                                 *out << Verbose(3) << "Set Shortest Path to " << FragmentSearch.ShortestPathList[OtherWalker->nr] << "." << endl;
    3963                                                 // add the bond in between to the SP list
    3964                                                 Binder = new bond(Walker, OtherWalker); // create a new bond in such a manner, that bond::rightatom is always the one more distant
    3965                                                 add(Binder, FragmentSearch.BondsPerSPList[2*(SP+1)+1]);
    3966                                                 FragmentSearch.BondsPerSPCount[SP+1]++;
    3967                                                 *out << Verbose(3) << "Added its bond to SP list, having now " << FragmentSearch.BondsPerSPCount[SP+1] << " item(s)." << endl;
    3968                                         } else {
    3969                                                 if (OtherWalker != Predecessor)
    3970                                                         *out << Verbose(3) << "Not passing on, as index of " << *OtherWalker << " " << OtherWalker->GetTrueFather()->nr << " is smaller than that of Root " << RootKeyNr << "." << endl;
    3971                                                 else
    3972                                                         *out << Verbose(3) << "This is my predecessor " << *Predecessor << "." << endl;
    3973                                         }
    3974                                 } else *out << Verbose(2) << "Is not in the restricted keyset or skipping hydrogen " << *OtherWalker << "." << endl;
    3975                         }
    3976                 }
    3977         }
    3978 
    3979         // outputting all list for debugging
    3980         *out << Verbose(0) << "Printing all found lists." << endl;
    3981         for(int i=1;i<Order;i++) {              // skip the root edge in the printing
    3982                 Binder = FragmentSearch.BondsPerSPList[2*i];
    3983                 *out << Verbose(1) << "Current SP level is " << i << "." << endl;
    3984                 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {
    3985                         Binder = Binder->next;
    3986                         *out << Verbose(2) << *Binder << endl;
    3987                 }
    3988         }
    3989 
    3990         // creating fragments with the found edge sets  (may be done in reverse order, faster)
    3991         SP = -1;        // the Root <-> Root edge must be subtracted!
    3992         for(int i=Order;i--;) { // sum up all found edges
    3993                 Binder = FragmentSearch.BondsPerSPList[2*i];
    3994                 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {
    3995                         Binder = Binder->next;
    3996                         SP ++;
    3997                 }
    3998         }
    3999         *out << Verbose(0) << "Total number of edges is " << SP << "." << endl;
    4000         if (SP >= (Order-1)) {
    4001                 // start with root (push on fragment stack)
    4002                 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl;
    4003                 FragmentSearch.FragmentSet->clear();
    4004                 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl;
    4005                 // prepare the subset and call the generator
    4006                 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList");
    4007                 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next;  // on SP level 0 there's only the root bond
    4008 
    4009                 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order);
    4010 
    4011                 Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList");
    4012         } else {
    4013                 *out << Verbose(0) << "Not enough total number of edges to build " << Order << "-body fragments." << endl;
    4014         }
    4015 
    4016         // as FragmentSearch structure is used only once, we don't have to clean it anymore
    4017         // remove root from stack
    4018         *out << Verbose(0) << "Removing root again from stack." << endl;
    4019         FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr);
    4020 
    4021         // free'ing the bonds lists
    4022         *out << Verbose(0) << "Free'ing all found lists. and resetting index lists" << endl;
    4023         for(int i=Order;i--;) {
    4024                 *out << Verbose(1) << "Current SP level is " << i << ": ";
    4025                 Binder = FragmentSearch.BondsPerSPList[2*i];
    4026                 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {
    4027                         Binder = Binder->next;
    4028                         // *out << "Removing atom " << Binder->leftatom->nr << " and " << Binder->rightatom->nr << "." << endl; // make sure numbers are local
    4029                         FragmentSearch.ShortestPathList[Binder->leftatom->nr] = -1;
    4030                         FragmentSearch.ShortestPathList[Binder->rightatom->nr] = -1;
    4031                 }
    4032                 // delete added bonds
    4033                 cleanup(FragmentSearch.BondsPerSPList[2*i], FragmentSearch.BondsPerSPList[2*i+1]);
    4034                 // also start and end node
    4035                 *out << "cleaned." << endl;
    4036         }
    4037 
    4038         // return list
    4039         *out << Verbose(0) << "End of PowerSetGenerator." << endl;
    4040         return (FragmentSearch.FragmentCounter - Counter);
     3899  int SP, AtomKeyNr;
     3900  atom *Walker = NULL, *OtherWalker = NULL, *Predecessor = NULL;
     3901  bond *Binder = NULL;
     3902  bond *CurrentEdge = NULL;
     3903  bond **BondsList = NULL;
     3904  int RootKeyNr = FragmentSearch.Root->GetTrueFather()->nr;
     3905  int Counter = FragmentSearch.FragmentCounter;
     3906  int RemainingWalkers;
     3907
     3908  *out << endl;
     3909  *out << Verbose(0) << "Begin of PowerSetGenerator with order " << Order << " at Root " << *FragmentSearch.Root << "." << endl;
     3910
     3911  // prepare Label and SP arrays of the BFS search
     3912  FragmentSearch.ShortestPathList[FragmentSearch.Root->nr] = 0;
     3913
     3914  // prepare root level (SP = 0) and a loop bond denoting Root
     3915  for (int i=1;i<Order;i++)
     3916    FragmentSearch.BondsPerSPCount[i] = 0;
     3917  FragmentSearch.BondsPerSPCount[0] = 1;
     3918  Binder = new bond(FragmentSearch.Root, FragmentSearch.Root);
     3919  add(Binder, FragmentSearch.BondsPerSPList[1]);
     3920
     3921  // do a BFS search to fill the SP lists and label the found vertices
     3922  // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into
     3923  // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning
     3924  // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth
     3925  // (EdgeinSPLevel) of this tree ...
     3926  // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence
     3927  // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction.
     3928  *out << endl;
     3929  *out << Verbose(0) << "Starting BFS analysis ..." << endl;
     3930  for (SP = 0; SP < (Order-1); SP++) {
     3931    *out << Verbose(1) << "New SP level reached: " << SP << ", creating new SP list with " << FragmentSearch.BondsPerSPCount[SP] << " item(s)";
     3932    if (SP > 0) {
     3933      *out << ", old level closed with " << FragmentSearch.BondsPerSPCount[SP-1] << " item(s)." << endl;
     3934      FragmentSearch.BondsPerSPCount[SP] = 0;
     3935    } else
     3936      *out << "." << endl;
     3937
     3938    RemainingWalkers = FragmentSearch.BondsPerSPCount[SP];
     3939    CurrentEdge = FragmentSearch.BondsPerSPList[2*SP];    /// start of this SP level's list
     3940    while (CurrentEdge->next != FragmentSearch.BondsPerSPList[2*SP+1]) {    /// end of this SP level's list
     3941      CurrentEdge = CurrentEdge->next;
     3942      RemainingWalkers--;
     3943      Walker = CurrentEdge->rightatom;    // rightatom is always the one more distant
     3944      Predecessor = CurrentEdge->leftatom;    // ... and leftatom is predecessor
     3945      AtomKeyNr = Walker->nr;
     3946      *out << Verbose(0) << "Current Walker is: " << *Walker << " with nr " << Walker->nr << " and SP of " << SP << ", with " << RemainingWalkers << " remaining walkers on this level." << endl;
     3947      // check for new sp level
     3948      // go through all its bonds
     3949      *out << Verbose(1) << "Going through all bonds of Walker." << endl;
     3950      for (int i=0;i<NumberOfBondsPerAtom[AtomKeyNr];i++) {
     3951        Binder = ListOfBondsPerAtom[AtomKeyNr][i];
     3952        OtherWalker = Binder->GetOtherAtom(Walker);
     3953        if ((RestrictedKeySet.find(OtherWalker->nr) != RestrictedKeySet.end())
     3954  #ifdef ADDHYDROGEN
     3955        && (OtherWalker->type->Z != 1)
     3956  #endif
     3957                                                              ) {  // skip hydrogens and restrict to fragment
     3958          *out << Verbose(2) << "Current partner is " << *OtherWalker << " with nr " << OtherWalker->nr << " in bond " << *Binder << "." << endl;
     3959          // set the label if not set (and push on root stack as well)
     3960          if ((OtherWalker != Predecessor) && (OtherWalker->GetTrueFather()->nr > RootKeyNr)) { // only pass through those with label bigger than Root's
     3961            FragmentSearch.ShortestPathList[OtherWalker->nr] = SP+1;
     3962            *out << Verbose(3) << "Set Shortest Path to " << FragmentSearch.ShortestPathList[OtherWalker->nr] << "." << endl;
     3963            // add the bond in between to the SP list
     3964            Binder = new bond(Walker, OtherWalker); // create a new bond in such a manner, that bond::rightatom is always the one more distant
     3965            add(Binder, FragmentSearch.BondsPerSPList[2*(SP+1)+1]);
     3966            FragmentSearch.BondsPerSPCount[SP+1]++;
     3967            *out << Verbose(3) << "Added its bond to SP list, having now " << FragmentSearch.BondsPerSPCount[SP+1] << " item(s)." << endl;
     3968          } else {
     3969            if (OtherWalker != Predecessor)
     3970              *out << Verbose(3) << "Not passing on, as index of " << *OtherWalker << " " << OtherWalker->GetTrueFather()->nr << " is smaller than that of Root " << RootKeyNr << "." << endl;
     3971            else
     3972              *out << Verbose(3) << "This is my predecessor " << *Predecessor << "." << endl;
     3973          }
     3974        } else *out << Verbose(2) << "Is not in the restricted keyset or skipping hydrogen " << *OtherWalker << "." << endl;
     3975      }
     3976    }
     3977  }
     3978
     3979  // outputting all list for debugging
     3980  *out << Verbose(0) << "Printing all found lists." << endl;
     3981  for(int i=1;i<Order;i++) {    // skip the root edge in the printing
     3982    Binder = FragmentSearch.BondsPerSPList[2*i];
     3983    *out << Verbose(1) << "Current SP level is " << i << "." << endl;
     3984    while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {
     3985      Binder = Binder->next;
     3986      *out << Verbose(2) << *Binder << endl;
     3987    }
     3988  }
     3989
     3990  // creating fragments with the found edge sets  (may be done in reverse order, faster)
     3991  SP = -1;  // the Root <-> Root edge must be subtracted!
     3992  for(int i=Order;i--;) { // sum up all found edges
     3993    Binder = FragmentSearch.BondsPerSPList[2*i];
     3994    while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {
     3995      Binder = Binder->next;
     3996      SP ++;
     3997    }
     3998  }
     3999  *out << Verbose(0) << "Total number of edges is " << SP << "." << endl;
     4000  if (SP >= (Order-1)) {
     4001    // start with root (push on fragment stack)
     4002    *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl;
     4003    FragmentSearch.FragmentSet->clear();
     4004    *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl;
     4005    // prepare the subset and call the generator
     4006    BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList");
     4007    BondsList[0] = FragmentSearch.BondsPerSPList[0]->next;  // on SP level 0 there's only the root bond
     4008
     4009    SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order);
     4010
     4011    Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList");
     4012  } else {
     4013    *out << Verbose(0) << "Not enough total number of edges to build " << Order << "-body fragments." << endl;
     4014  }
     4015
     4016  // as FragmentSearch structure is used only once, we don't have to clean it anymore
     4017  // remove root from stack
     4018  *out << Verbose(0) << "Removing root again from stack." << endl;
     4019  FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr);
     4020
     4021  // free'ing the bonds lists
     4022  *out << Verbose(0) << "Free'ing all found lists. and resetting index lists" << endl;
     4023  for(int i=Order;i--;) {
     4024    *out << Verbose(1) << "Current SP level is " << i << ": ";
     4025    Binder = FragmentSearch.BondsPerSPList[2*i];
     4026    while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {
     4027      Binder = Binder->next;
     4028      // *out << "Removing atom " << Binder->leftatom->nr << " and " << Binder->rightatom->nr << "." << endl; // make sure numbers are local
     4029      FragmentSearch.ShortestPathList[Binder->leftatom->nr] = -1;
     4030      FragmentSearch.ShortestPathList[Binder->rightatom->nr] = -1;
     4031    }
     4032    // delete added bonds
     4033    cleanup(FragmentSearch.BondsPerSPList[2*i], FragmentSearch.BondsPerSPList[2*i+1]);
     4034    // also start and end node
     4035    *out << "cleaned." << endl;
     4036  }
     4037
     4038  // return list
     4039  *out << Verbose(0) << "End of PowerSetGenerator." << endl;
     4040  return (FragmentSearch.FragmentCounter - Counter);
    40414041};
    40424042
     
    40494049void molecule::ScanForPeriodicCorrection(ofstream *out)
    40504050{
    4051         bond *Binder = NULL;
    4052         bond *OtherBinder = NULL;
    4053         atom *Walker = NULL;
    4054         atom *OtherWalker = NULL;
    4055         double *matrix = ReturnFullMatrixforSymmetric(cell_size);
    4056         enum Shading *ColorList = NULL;
    4057         double tmp;
    4058         Vector Translationvector;
    4059         //class StackClass<atom *> *CompStack = NULL;
    4060         class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);
    4061         bool flag = true;
    4062 
    4063         *out << Verbose(2) << "Begin of ScanForPeriodicCorrection." << endl;
    4064 
    4065         ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::ScanForPeriodicCorrection: *ColorList");
    4066         while (flag) {
    4067                 // remove bonds that are beyond bonddistance
    4068                 for(int i=NDIM;i--;)
    4069                         Translationvector.x[i] = 0.;
    4070                 // scan all bonds
    4071                 Binder = first;
    4072                 flag = false;
    4073                 while ((!flag) && (Binder->next != last)) {
    4074                         Binder = Binder->next;
    4075                         for (int i=NDIM;i--;) {
    4076                                 tmp = fabs(Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]);
    4077                                 //*out << Verbose(3) << "Checking " << i << "th distance of " << *Binder->leftatom << " to " << *Binder->rightatom << ": " << tmp << "." << endl;
    4078                                 if (tmp > BondDistance) {
    4079                                         OtherBinder = Binder->next; // note down binding partner for later re-insertion
    4080                                         unlink(Binder); // unlink bond
    4081                                         *out << Verbose(2) << "Correcting at bond " << *Binder << "." << endl;
    4082                                         flag = true;
    4083                                         break;
    4084                                 }
    4085                         }
    4086                 }
    4087                 if (flag) {
    4088                         // create translation vector from their periodically modified distance
    4089                         for (int i=NDIM;i--;) {
    4090                                 tmp = Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i];
    4091                                 if (fabs(tmp) > BondDistance)
    4092                                         Translationvector.x[i] = (tmp < 0) ? +1. : -1.;
    4093                         }
    4094                         Translationvector.MatrixMultiplication(matrix);
    4095                         //*out << Verbose(3) << "Translation vector is ";
    4096                         Translationvector.Output(out);
    4097                         *out << endl;
    4098                         // apply to all atoms of first component via BFS
    4099                         for (int i=AtomCount;i--;)
    4100                                 ColorList[i] = white;
    4101                         AtomStack->Push(Binder->leftatom);
    4102                         while (!AtomStack->IsEmpty()) {
    4103                                 Walker = AtomStack->PopFirst();
    4104                                 //*out << Verbose (3) << "Current Walker is: " << *Walker << "." << endl;
    4105                                 ColorList[Walker->nr] = black;          // mark as explored
    4106                                 Walker->x.AddVector(&Translationvector); // translate
    4107                                 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {  // go through all binding partners
    4108                                         if (ListOfBondsPerAtom[Walker->nr][i] != Binder) {
    4109                                                 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
    4110                                                 if (ColorList[OtherWalker->nr] == white) {
    4111                                                         AtomStack->Push(OtherWalker); // push if yet unexplored
    4112                                                 }
    4113                                         }
    4114                                 }
    4115                         }
    4116                         // re-add bond
    4117                         link(Binder, OtherBinder);
    4118                 } else {
    4119                         *out << Verbose(3) << "No corrections for this fragment." << endl;
    4120                 }
    4121                 //delete(CompStack);
    4122         }
    4123 
    4124         // free allocated space from ReturnFullMatrixforSymmetric()
    4125         delete(AtomStack);
    4126         Free((void **)&ColorList, "molecule::ScanForPeriodicCorrection: *ColorList");
    4127         Free((void **)&matrix, "molecule::ScanForPeriodicCorrection: *matrix");
    4128         *out << Verbose(2) << "End of ScanForPeriodicCorrection." << endl;
     4051  bond *Binder = NULL;
     4052  bond *OtherBinder = NULL;
     4053  atom *Walker = NULL;
     4054  atom *OtherWalker = NULL;
     4055  double *matrix = ReturnFullMatrixforSymmetric(cell_size);
     4056  enum Shading *ColorList = NULL;
     4057  double tmp;
     4058  Vector Translationvector;
     4059  //class StackClass<atom *> *CompStack = NULL;
     4060  class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);
     4061  bool flag = true;
     4062
     4063  *out << Verbose(2) << "Begin of ScanForPeriodicCorrection." << endl;
     4064
     4065  ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::ScanForPeriodicCorrection: *ColorList");
     4066  while (flag) {
     4067    // remove bonds that are beyond bonddistance
     4068    for(int i=NDIM;i--;)
     4069      Translationvector.x[i] = 0.;
     4070    // scan all bonds
     4071    Binder = first;
     4072    flag = false;
     4073    while ((!flag) && (Binder->next != last)) {
     4074      Binder = Binder->next;
     4075      for (int i=NDIM;i--;) {
     4076        tmp = fabs(Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]);
     4077        //*out << Verbose(3) << "Checking " << i << "th distance of " << *Binder->leftatom << " to " << *Binder->rightatom << ": " << tmp << "." << endl;
     4078        if (tmp > BondDistance) {
     4079          OtherBinder = Binder->next; // note down binding partner for later re-insertion
     4080          unlink(Binder);  // unlink bond
     4081          *out << Verbose(2) << "Correcting at bond " << *Binder << "." << endl;
     4082          flag = true;
     4083          break;
     4084        }
     4085      }
     4086    }
     4087    if (flag) {
     4088      // create translation vector from their periodically modified distance
     4089      for (int i=NDIM;i--;) {
     4090        tmp = Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i];
     4091        if (fabs(tmp) > BondDistance)
     4092          Translationvector.x[i] = (tmp < 0) ? +1. : -1.;
     4093      }
     4094      Translationvector.MatrixMultiplication(matrix);
     4095      //*out << Verbose(3) << "Translation vector is ";
     4096      Translationvector.Output(out);
     4097      *out << endl;
     4098      // apply to all atoms of first component via BFS
     4099      for (int i=AtomCount;i--;)
     4100        ColorList[i] = white;
     4101      AtomStack->Push(Binder->leftatom);
     4102      while (!AtomStack->IsEmpty()) {
     4103        Walker = AtomStack->PopFirst();
     4104        //*out << Verbose (3) << "Current Walker is: " << *Walker << "." << endl;
     4105        ColorList[Walker->nr] = black;    // mark as explored
     4106        Walker->x.AddVector(&Translationvector); // translate
     4107        for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {  // go through all binding partners
     4108          if (ListOfBondsPerAtom[Walker->nr][i] != Binder) {
     4109            OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
     4110            if (ColorList[OtherWalker->nr] == white) {
     4111              AtomStack->Push(OtherWalker); // push if yet unexplored
     4112            }
     4113          }
     4114        }
     4115      }
     4116      // re-add bond
     4117      link(Binder, OtherBinder);
     4118    } else {
     4119      *out << Verbose(3) << "No corrections for this fragment." << endl;
     4120    }
     4121    //delete(CompStack);
     4122  }
     4123
     4124  // free allocated space from ReturnFullMatrixforSymmetric()
     4125  delete(AtomStack);
     4126  Free((void **)&ColorList, "molecule::ScanForPeriodicCorrection: *ColorList");
     4127  Free((void **)&matrix, "molecule::ScanForPeriodicCorrection: *matrix");
     4128  *out << Verbose(2) << "End of ScanForPeriodicCorrection." << endl;
    41294129};
    41304130
     
    41354135double * molecule::ReturnFullMatrixforSymmetric(double *symm)
    41364136{
    4137         double *matrix = (double *) Malloc(sizeof(double)*NDIM*NDIM, "molecule::ReturnFullMatrixforSymmetric: *matrix");
    4138         matrix[0] = symm[0];
    4139         matrix[1] = symm[1];
    4140         matrix[2] = symm[3];
    4141         matrix[3] = symm[1];
    4142         matrix[4] = symm[2];
    4143         matrix[5] = symm[4];
    4144         matrix[6] = symm[3];
    4145         matrix[7] = symm[4];
    4146         matrix[8] = symm[5];
    4147         return matrix;
     4137  double *matrix = (double *) Malloc(sizeof(double)*NDIM*NDIM, "molecule::ReturnFullMatrixforSymmetric: *matrix");
     4138  matrix[0] = symm[0];
     4139  matrix[1] = symm[1];
     4140  matrix[2] = symm[3];
     4141  matrix[3] = symm[1];
     4142  matrix[4] = symm[2];
     4143  matrix[5] = symm[4];
     4144  matrix[6] = symm[3];
     4145  matrix[7] = symm[4];
     4146  matrix[8] = symm[5];
     4147  return matrix;
    41484148};
    41494149
    41504150bool KeyCompare::operator() (const KeySet SubgraphA, const KeySet SubgraphB) const
    41514151{
    4152         //cout << "my check is used." << endl;
    4153         if (SubgraphA.size() < SubgraphB.size()) {
    4154                 return true;
    4155         } else {
    4156                 if (SubgraphA.size() > SubgraphB.size()) {
    4157                         return false;
    4158                 } else {
    4159                         KeySet::iterator IteratorA = SubgraphA.begin();
    4160                         KeySet::iterator IteratorB = SubgraphB.begin();
    4161                         while ((IteratorA != SubgraphA.end()) && (IteratorB != SubgraphB.end())) {
    4162                                 if ((*IteratorA) <      (*IteratorB))
    4163                                         return true;
    4164                                 else if ((*IteratorA) > (*IteratorB)) {
    4165                                                 return false;
    4166                                         } // else, go on to next index
    4167                                 IteratorA++;
    4168                                 IteratorB++;
    4169                         } // end of while loop
    4170                 }// end of check in case of equal sizes
    4171         }
    4172         return false; // if we reach this point, they are equal
     4152  //cout << "my check is used." << endl;
     4153  if (SubgraphA.size() < SubgraphB.size()) {
     4154    return true;
     4155  } else {
     4156    if (SubgraphA.size() > SubgraphB.size()) {
     4157      return false;
     4158    } else {
     4159      KeySet::iterator IteratorA = SubgraphA.begin();
     4160      KeySet::iterator IteratorB = SubgraphB.begin();
     4161      while ((IteratorA != SubgraphA.end()) && (IteratorB != SubgraphB.end())) {
     4162        if ((*IteratorA) <  (*IteratorB))
     4163          return true;
     4164        else if ((*IteratorA) > (*IteratorB)) {
     4165            return false;
     4166          } // else, go on to next index
     4167        IteratorA++;
     4168        IteratorB++;
     4169      } // end of while loop
     4170    }// end of check in case of equal sizes
     4171  }
     4172  return false; // if we reach this point, they are equal
    41734173};
    41744174
    41754175//bool operator < (KeySet SubgraphA, KeySet SubgraphB)
    41764176//{
    4177 //      return KeyCompare(SubgraphA, SubgraphB);
     4177//  return KeyCompare(SubgraphA, SubgraphB);
    41784178//};
    41794179
     
    41874187inline void InsertFragmentIntoGraph(ofstream *out, struct UniqueFragments *Fragment)
    41884188{
    4189         GraphTestPair testGraphInsert;
    4190 
    4191         testGraphInsert = Fragment->Leaflet->insert(GraphPair (*Fragment->FragmentSet,pair<int,double>(Fragment->FragmentCounter,Fragment->TEFactor))); // store fragment number and current factor
    4192         if (testGraphInsert.second) {
    4193                 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " successfully inserted." << endl;
    4194                 Fragment->FragmentCounter++;
    4195         } else {
    4196                 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;
    4197                 ((*(testGraphInsert.first)).second).second += Fragment->TEFactor;       // increase the "created" counter
    4198                 *out << Verbose(2) << "New factor is " << ((*(testGraphInsert.first)).second).second << "." << endl;
    4199         }
     4189  GraphTestPair testGraphInsert;
     4190
     4191  testGraphInsert = Fragment->Leaflet->insert(GraphPair (*Fragment->FragmentSet,pair<int,double>(Fragment->FragmentCounter,Fragment->TEFactor)));  // store fragment number and current factor
     4192  if (testGraphInsert.second) {
     4193    *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " successfully inserted." << endl;
     4194    Fragment->FragmentCounter++;
     4195  } else {
     4196    *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;
     4197    ((*(testGraphInsert.first)).second).second += Fragment->TEFactor;  // increase the "created" counter
     4198    *out << Verbose(2) << "New factor is " << ((*(testGraphInsert.first)).second).second << "." << endl;
     4199  }
    42004200};
    42014201//void inline InsertIntoGraph(ofstream *out, KeyStack &stack, Graph &graph, int *counter, double factor)
    42024202//{
    4203 //      // copy stack contents to set and call overloaded function again
    4204 //      KeySet set;
    4205 //      for(KeyStack::iterator runner = stack.begin(); runner != stack.begin(); runner++)
    4206 //              set.insert((*runner));
    4207 //      InsertIntoGraph(out, set, graph, counter, factor);
     4203//  // copy stack contents to set and call overloaded function again
     4204//  KeySet set;
     4205//  for(KeyStack::iterator runner = stack.begin(); runner != stack.begin(); runner++)
     4206//    set.insert((*runner));
     4207//  InsertIntoGraph(out, set, graph, counter, factor);
    42084208//};
    42094209
     
    42164216inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter)
    42174217{
    4218         GraphTestPair testGraphInsert;
    4219 
    4220         for(Graph::iterator runner = graph2.begin(); runner != graph2.end(); runner++) {
    4221                 testGraphInsert = graph1.insert(GraphPair ((*runner).first,pair<int,double>((*counter)++,((*runner).second).second)));  // store fragment number and current factor
    4222                 if (testGraphInsert.second) {
    4223                         *out << Verbose(2) << "KeySet " << (*counter)-1 << " successfully inserted." << endl;
    4224                 } else {
    4225                         *out << Verbose(2) << "KeySet " << (*counter)-1 << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;
    4226                         ((*(testGraphInsert.first)).second).second += (*runner).second.second;
    4227                         *out << Verbose(2) << "New factor is " << (*(testGraphInsert.first)).second.second << "." << endl;
    4228                 }
    4229         }
     4218  GraphTestPair testGraphInsert;
     4219
     4220  for(Graph::iterator runner = graph2.begin(); runner != graph2.end(); runner++) {
     4221    testGraphInsert = graph1.insert(GraphPair ((*runner).first,pair<int,double>((*counter)++,((*runner).second).second)));  // store fragment number and current factor
     4222    if (testGraphInsert.second) {
     4223      *out << Verbose(2) << "KeySet " << (*counter)-1 << " successfully inserted." << endl;
     4224    } else {
     4225      *out << Verbose(2) << "KeySet " << (*counter)-1 << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;
     4226      ((*(testGraphInsert.first)).second).second += (*runner).second.second;
     4227      *out << Verbose(2) << "New factor is " << (*(testGraphInsert.first)).second.second << "." << endl;
     4228    }
     4229  }
    42304230};
    42314231
     
    42344234 * -# constructs a complete keyset of the molecule
    42354235 * -# In a loop over all possible roots from the given rootstack
    4236  *      -# increases order of root site
    4237  *      -# calls PowerSetGenerator with this order, the complete keyset and the rootkeynr
    4238  *      -# for all consecutive lower levels PowerSetGenerator is called with the suborder, the higher order keyset
     4236 *  -# increases order of root site
     4237 *  -# calls PowerSetGenerator with this order, the complete keyset and the rootkeynr
     4238 *  -# for all consecutive lower levels PowerSetGenerator is called with the suborder, the higher order keyset
    42394239as the restricted one and each site in the set as the root)
    4240  *      -# these are merged into a fragment list of keysets
     4240 *  -# these are merged into a fragment list of keysets
    42414241 * -# All fragment lists (for all orders, i.e. from all destination fields) are merged into one list for return
    42424242 * Important only is that we create all fragments, it is not important if we create them more than once
     
    42504250void molecule::FragmentBOSSANOVA(ofstream *out, Graph *&FragmentList, KeyStack &RootStack, int *MinimumRingSize)
    42514251{
    4252         Graph ***FragmentLowerOrdersList = NULL;
    4253         int NumLevels, NumMolecules, TotalNumMolecules = 0, *NumMoleculesOfOrder = NULL;
    4254         int counter = 0, Order;
    4255         int UpgradeCount = RootStack.size();
    4256         KeyStack FragmentRootStack;
    4257         int RootKeyNr, RootNr;
    4258         struct UniqueFragments FragmentSearch;
    4259 
    4260         *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl;
    4261 
    4262         // FragmentLowerOrdersList is a 2D-array of pointer to MoleculeListClass objects, one dimension represents the ANOVA expansion of a single order (i.e. 5)
    4263         // with all needed lower orders that are subtracted, the other dimension is the BondOrder (i.e. from 1 to 5)
    4264         NumMoleculesOfOrder = (int *) Malloc(sizeof(int)*UpgradeCount, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder");
    4265         FragmentLowerOrdersList = (Graph ***) Malloc(sizeof(Graph **)*UpgradeCount, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList");
    4266 
    4267         // initialise the fragments structure
    4268         FragmentSearch.ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::PowerSetGenerator: *ShortestPathList");
    4269         FragmentSearch.FragmentCounter = 0;
    4270         FragmentSearch.FragmentSet = new KeySet;
    4271         FragmentSearch.Root = FindAtom(RootKeyNr);
    4272         for (int i=AtomCount;i--;) {
    4273                 FragmentSearch.ShortestPathList[i] = -1;
    4274         }
    4275 
    4276         // Construct the complete KeySet which we need for topmost level only (but for all Roots)
    4277         atom *Walker = start;
    4278         KeySet CompleteMolecule;
    4279         while (Walker->next != end) {
    4280                 Walker = Walker->next;
    4281                 CompleteMolecule.insert(Walker->GetTrueFather()->nr);
    4282         }
    4283 
    4284         // 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
    4285         // 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),
    4286         // hence we have overall four 2th order levels for splitting. This also allows for putting all into a single array (FragmentLowerOrdersList[])
    4287         // 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)
    4288         RootNr = 0;      // counts through the roots in RootStack
    4289         while ((RootNr < UpgradeCount) && (!RootStack.empty())) {
    4290                 RootKeyNr = RootStack.front();
    4291                 RootStack.pop_front();
    4292                 Walker = FindAtom(RootKeyNr);
    4293                 // check cyclic lengths
    4294                 //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) {
    4295                 //      *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;
    4296                 //} else
    4297                 {
    4298                         // increase adaptive order by one
    4299                         Walker->GetTrueFather()->AdaptiveOrder++;
    4300                         Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder;
    4301 
    4302                         // initialise Order-dependent entries of UniqueFragments structure
    4303                         FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList");
    4304                         FragmentSearch.BondsPerSPCount = (int *) Malloc(sizeof(int)*Order, "molecule::PowerSetGenerator: *BondsPerSPCount");
    4305                         for (int i=Order;i--;) {
    4306                                 FragmentSearch.BondsPerSPList[2*i] = new bond();                // start node
    4307                                 FragmentSearch.BondsPerSPList[2*i+1] = new bond();      // end node
    4308                                 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1];                // intertwine these two
    4309                                 FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i];
    4310                                 FragmentSearch.BondsPerSPCount[i] = 0;
    4311                         }
    4312 
    4313                         // allocate memory for all lower level orders in this 1D-array of ptrs
    4314                         NumLevels = 1 << (Order-1); // (int)pow(2,Order);
    4315                         FragmentLowerOrdersList[RootNr] = (Graph **) Malloc(sizeof(Graph *)*NumLevels, "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]");
    4316                         for (int i=0;i<NumLevels;i++)
    4317                                 FragmentLowerOrdersList[RootNr][i] = NULL;
    4318 
    4319                         // create top order where nothing is reduced
    4320                         *out << Verbose(0) << "==============================================================================================================" << endl;
    4321                         *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << "
    4322 
    4323                         // Create list of Graphs of current Bond Order (i.e. F_{ij})
    4324                         FragmentLowerOrdersList[RootNr][0] =    new Graph;
    4325                         FragmentSearch.TEFactor = 1.;
    4326                         FragmentSearch.Leaflet = FragmentLowerOrdersList[RootNr][0];                    // set to insertion graph
    4327                         FragmentSearch.Root = Walker;
    4328                         NumMoleculesOfOrder[RootNr] = PowerSetGenerator(out, Walker->AdaptiveOrder, FragmentSearch, CompleteMolecule);
    4329                         *out << Verbose(1) << "Number of resulting KeySets is: " << NumMoleculesOfOrder[RootNr] << "." << endl;
    4330                         if (NumMoleculesOfOrder[RootNr] != 0) {
    4331                                 NumMolecules = 0;
    4332 
    4333                                 // we don't have to dive into suborders! These keysets are all already created on lower orders!
    4334                                 // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed)
    4335 
    4336 //                              if ((NumLevels >> 1) > 0) {
    4337 //                                      // create lower order fragments
    4338 //                                      *out << Verbose(0) << "Creating list of unique fragments of lower Bond Order terms to be subtracted." << endl;
    4339 //                                      Order = Walker->AdaptiveOrder;
    4340 //                                      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)
    4341 //                                              // step down to next order at (virtual) boundary of powers of 2 in array
    4342 //                                              while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order))
    4343 //                                                      Order--;
    4344 //                                              *out << Verbose(0) << "Current Order is: " << Order << "." << endl;
    4345 //                                              for (int SubOrder=Order-1;SubOrder>0;SubOrder--) {
    4346 //                                                      int dest = source + (1 << (Walker->AdaptiveOrder-(SubOrder+1)));
    4347 //                                                      *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl;
    4348 //                                                      *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl;
     4252  Graph ***FragmentLowerOrdersList = NULL;
     4253  int NumLevels, NumMolecules, TotalNumMolecules = 0, *NumMoleculesOfOrder = NULL;
     4254  int counter = 0, Order;
     4255  int UpgradeCount = RootStack.size();
     4256  KeyStack FragmentRootStack;
     4257  int RootKeyNr, RootNr;
     4258  struct UniqueFragments FragmentSearch;
     4259
     4260  *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl;
     4261
     4262  // FragmentLowerOrdersList is a 2D-array of pointer to MoleculeListClass objects, one dimension represents the ANOVA expansion of a single order (i.e. 5)
     4263  // with all needed lower orders that are subtracted, the other dimension is the BondOrder (i.e. from 1 to 5)
     4264  NumMoleculesOfOrder = (int *) Malloc(sizeof(int)*UpgradeCount, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder");
     4265  FragmentLowerOrdersList = (Graph ***) Malloc(sizeof(Graph **)*UpgradeCount, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList");
     4266
     4267  // initialise the fragments structure
     4268  FragmentSearch.ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::PowerSetGenerator: *ShortestPathList");
     4269  FragmentSearch.FragmentCounter = 0;
     4270  FragmentSearch.FragmentSet = new KeySet;
     4271  FragmentSearch.Root = FindAtom(RootKeyNr);
     4272  for (int i=AtomCount;i--;) {
     4273    FragmentSearch.ShortestPathList[i] = -1;
     4274  }
     4275
     4276  // Construct the complete KeySet which we need for topmost level only (but for all Roots)
     4277  atom *Walker = start;
     4278  KeySet CompleteMolecule;
     4279  while (Walker->next != end) {
     4280    Walker = Walker->next;
     4281    CompleteMolecule.insert(Walker->GetTrueFather()->nr);
     4282  }
     4283
     4284  // 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
     4285  // 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),
     4286  // hence we have overall four 2th order levels for splitting. This also allows for putting all into a single array (FragmentLowerOrdersList[])
     4287  // 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)
     4288  RootNr = 0;  // counts through the roots in RootStack
     4289  while ((RootNr < UpgradeCount) && (!RootStack.empty())) {
     4290    RootKeyNr = RootStack.front();
     4291    RootStack.pop_front();
     4292    Walker = FindAtom(RootKeyNr);
     4293    // check cyclic lengths
     4294    //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) {
     4295    //  *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;
     4296    //} else
     4297    {
     4298      // increase adaptive order by one
     4299      Walker->GetTrueFather()->AdaptiveOrder++;
     4300      Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder;
     4301
     4302      // initialise Order-dependent entries of UniqueFragments structure
     4303      FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList");
     4304      FragmentSearch.BondsPerSPCount = (int *) Malloc(sizeof(int)*Order, "molecule::PowerSetGenerator: *BondsPerSPCount");
     4305      for (int i=Order;i--;) {
     4306        FragmentSearch.BondsPerSPList[2*i] = new bond();    // start node
     4307        FragmentSearch.BondsPerSPList[2*i+1] = new bond();  // end node
     4308        FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1];    // intertwine these two
     4309        FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i];
     4310        FragmentSearch.BondsPerSPCount[i] = 0;
     4311      }
     4312
     4313      // allocate memory for all lower level orders in this 1D-array of ptrs
     4314      NumLevels = 1 << (Order-1); // (int)pow(2,Order);
     4315      FragmentLowerOrdersList[RootNr] = (Graph **) Malloc(sizeof(Graph *)*NumLevels, "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]");
     4316      for (int i=0;i<NumLevels;i++)
     4317        FragmentLowerOrdersList[RootNr][i] = NULL;
     4318
     4319      // create top order where nothing is reduced
     4320      *out << Verbose(0) << "==============================================================================================================" << endl;
     4321      *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << "
     4322
     4323      // Create list of Graphs of current Bond Order (i.e. F_{ij})
     4324      FragmentLowerOrdersList[RootNr][0] =  new Graph;
     4325      FragmentSearch.TEFactor = 1.;
     4326      FragmentSearch.Leaflet = FragmentLowerOrdersList[RootNr][0];      // set to insertion graph
     4327      FragmentSearch.Root = Walker;
     4328      NumMoleculesOfOrder[RootNr] = PowerSetGenerator(out, Walker->AdaptiveOrder, FragmentSearch, CompleteMolecule);
     4329      *out << Verbose(1) << "Number of resulting KeySets is: " << NumMoleculesOfOrder[RootNr] << "." << endl;
     4330      if (NumMoleculesOfOrder[RootNr] != 0) {
     4331        NumMolecules = 0;
     4332
     4333        // we don't have to dive into suborders! These keysets are all already created on lower orders!
     4334        // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed)
     4335
     4336//        if ((NumLevels >> 1) > 0) {
     4337//          // create lower order fragments
     4338//          *out << Verbose(0) << "Creating list of unique fragments of lower Bond Order terms to be subtracted." << endl;
     4339//          Order = Walker->AdaptiveOrder;
     4340//          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)
     4341//            // step down to next order at (virtual) boundary of powers of 2 in array
     4342//            while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order))
     4343//              Order--;
     4344//            *out << Verbose(0) << "Current Order is: " << Order << "." << endl;
     4345//            for (int SubOrder=Order-1;SubOrder>0;SubOrder--) {
     4346//              int dest = source + (1 << (Walker->AdaptiveOrder-(SubOrder+1)));
     4347//              *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl;
     4348//              *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl;
    43494349//
    4350 //                                                      // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules
    4351 //                                                      //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl;
    4352 //                                                      //NumMolecules = 0;
    4353 //                                                      FragmentLowerOrdersList[RootNr][dest] = new Graph;
    4354 //                                                      for(Graph::iterator runner = (*FragmentLowerOrdersList[RootNr][source]).begin();runner != (*FragmentLowerOrdersList[RootNr][source]).end(); runner++) {
    4355 //                                                              for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) {
    4356 //                                                                      Graph TempFragmentList;
    4357 //                                                                      FragmentSearch.TEFactor = -(*runner).second.second;
    4358 //                                                                      FragmentSearch.Leaflet = &TempFragmentList;                     // set to insertion graph
    4359 //                                                                      FragmentSearch.Root = FindAtom(*sprinter);
    4360 //                                                                      NumMoleculesOfOrder[RootNr] += PowerSetGenerator(out, SubOrder, FragmentSearch, (*runner).first);
    4361 //                                                                      // insert new keysets FragmentList into FragmentLowerOrdersList[Walker->AdaptiveOrder-1][dest]
    4362 //                                                                      *out << Verbose(1) << "Merging resulting key sets with those present in destination " << dest << "." << endl;
    4363 //                                                                      InsertGraphIntoGraph(out, *FragmentLowerOrdersList[RootNr][dest], TempFragmentList, &NumMolecules);
    4364 //                                                              }
    4365 //                                                      }
    4366 //                                                      *out << Verbose(1) << "Number of resulting molecules for SubOrder " << SubOrder << " is: " << NumMolecules << "." << endl;
    4367 //                                              }
    4368 //                                      }
    4369 //                              }
    4370                         } else {
    4371                                 Walker->GetTrueFather()->MaxOrder = true;
    4372 //                              *out << Verbose(1) << "Hence, we don't dive into SubOrders ... " << endl;
    4373                         }
    4374                         // now, we have completely filled each cell of FragmentLowerOrdersList[] for the current Walker->AdaptiveOrder
    4375                         //NumMoleculesOfOrder[Walker->AdaptiveOrder-1] = NumMolecules;
    4376                         TotalNumMolecules += NumMoleculesOfOrder[RootNr];
    4377 //                      *out << Verbose(1) << "Number of resulting molecules for Order " << (int)Walker->GetTrueFather()->AdaptiveOrder << " is: " << NumMoleculesOfOrder[RootNr] << "." << endl;
    4378                         RootStack.push_back(RootKeyNr); // put back on stack
    4379                         RootNr++;
    4380 
    4381                         // free Order-dependent entries of UniqueFragments structure for next loop cycle
    4382                         Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount");
    4383                         for (int i=Order;i--;) {
    4384                                 delete(FragmentSearch.BondsPerSPList[2*i]);
    4385                                 delete(FragmentSearch.BondsPerSPList[2*i+1]);
    4386                         }
    4387                         Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList");
    4388                 }
    4389         }
    4390         *out << Verbose(0) << "==============================================================================================================" << endl;
    4391         *out << Verbose(1) << "Total number of resulting molecules is: " << TotalNumMolecules << "." << endl;
    4392         *out << Verbose(0) << "==============================================================================================================" << endl;
    4393 
    4394         // cleanup FragmentSearch structure
    4395         Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList");
    4396         delete(FragmentSearch.FragmentSet);
    4397 
    4398         // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein)
    4399         // 5433222211111111
    4400         // 43221111
    4401         // 3211
    4402         // 21
    4403         // 1
    4404 
    4405         // Subsequently, we combine all into a single list (FragmentList)
    4406 
    4407         *out << Verbose(0) << "Combining the lists of all orders per order and finally into a single one." << endl;
    4408         if (FragmentList == NULL) {
    4409                 FragmentList = new Graph;
    4410                 counter = 0;
    4411         } else {
    4412                 counter = FragmentList->size();
    4413         }
    4414         RootNr = 0;
    4415         while (!RootStack.empty()) {
    4416                 RootKeyNr = RootStack.front();
    4417                 RootStack.pop_front();
    4418                 Walker = FindAtom(RootKeyNr);
    4419                 NumLevels = 1 << (Walker->AdaptiveOrder - 1);
    4420                 for(int i=0;i<NumLevels;i++) {
    4421                         if (FragmentLowerOrdersList[RootNr][i] != NULL) {
    4422                                 InsertGraphIntoGraph(out, *FragmentList, (*FragmentLowerOrdersList[RootNr][i]), &counter);
    4423                                 delete(FragmentLowerOrdersList[RootNr][i]);
    4424                         }
    4425                 }
    4426                 Free((void **)&FragmentLowerOrdersList[RootNr], "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]");
    4427                 RootNr++;
    4428         }
    4429         Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList");
    4430         Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder");
    4431 
    4432         *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl;
     4350//              // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules
     4351//              //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl;
     4352//              //NumMolecules = 0;
     4353//              FragmentLowerOrdersList[RootNr][dest] = new Graph;
     4354//              for(Graph::iterator runner = (*FragmentLowerOrdersList[RootNr][source]).begin();runner != (*FragmentLowerOrdersList[RootNr][source]).end(); runner++) {
     4355//                for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) {
     4356//                  Graph TempFragmentList;
     4357//                  FragmentSearch.TEFactor = -(*runner).second.second;
     4358//                  FragmentSearch.Leaflet = &TempFragmentList;      // set to insertion graph
     4359//                  FragmentSearch.Root = FindAtom(*sprinter);
     4360//                  NumMoleculesOfOrder[RootNr] += PowerSetGenerator(out, SubOrder, FragmentSearch, (*runner).first);
     4361//                  // insert new keysets FragmentList into FragmentLowerOrdersList[Walker->AdaptiveOrder-1][dest]
     4362//                  *out << Verbose(1) << "Merging resulting key sets with those present in destination " << dest << "." << endl;
     4363//                  InsertGraphIntoGraph(out, *FragmentLowerOrdersList[RootNr][dest], TempFragmentList, &NumMolecules);
     4364//                }
     4365//              }
     4366//              *out << Verbose(1) << "Number of resulting molecules for SubOrder " << SubOrder << " is: " << NumMolecules << "." << endl;
     4367//            }
     4368//          }
     4369//        }
     4370      } else {
     4371        Walker->GetTrueFather()->MaxOrder = true;
     4372//        *out << Verbose(1) << "Hence, we don't dive into SubOrders ... " << endl;
     4373      }
     4374      // now, we have completely filled each cell of FragmentLowerOrdersList[] for the current Walker->AdaptiveOrder
     4375      //NumMoleculesOfOrder[Walker->AdaptiveOrder-1] = NumMolecules;
     4376      TotalNumMolecules += NumMoleculesOfOrder[RootNr];
     4377//      *out << Verbose(1) << "Number of resulting molecules for Order " << (int)Walker->GetTrueFather()->AdaptiveOrder << " is: " << NumMoleculesOfOrder[RootNr] << "." << endl;
     4378      RootStack.push_back(RootKeyNr); // put back on stack
     4379      RootNr++;
     4380
     4381      // free Order-dependent entries of UniqueFragments structure for next loop cycle
     4382      Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount");
     4383      for (int i=Order;i--;) {
     4384        delete(FragmentSearch.BondsPerSPList[2*i]);
     4385        delete(FragmentSearch.BondsPerSPList[2*i+1]);
     4386      }
     4387      Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList");
     4388    }
     4389  }
     4390  *out << Verbose(0) << "==============================================================================================================" << endl;
     4391  *out << Verbose(1) << "Total number of resulting molecules is: " << TotalNumMolecules << "." << endl;
     4392  *out << Verbose(0) << "==============================================================================================================" << endl;
     4393
     4394  // cleanup FragmentSearch structure
     4395  Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList");
     4396  delete(FragmentSearch.FragmentSet);
     4397
     4398  // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein)
     4399  // 5433222211111111
     4400  // 43221111
     4401  // 3211
     4402  // 21
     4403  // 1
     4404
     4405  // Subsequently, we combine all into a single list (FragmentList)
     4406
     4407  *out << Verbose(0) << "Combining the lists of all orders per order and finally into a single one." << endl;
     4408  if (FragmentList == NULL) {
     4409    FragmentList = new Graph;
     4410    counter = 0;
     4411  } else {
     4412    counter = FragmentList->size();
     4413  }
     4414  RootNr = 0;
     4415  while (!RootStack.empty()) {
     4416    RootKeyNr = RootStack.front();
     4417    RootStack.pop_front();
     4418    Walker = FindAtom(RootKeyNr);
     4419    NumLevels = 1 << (Walker->AdaptiveOrder - 1);
     4420    for(int i=0;i<NumLevels;i++) {
     4421      if (FragmentLowerOrdersList[RootNr][i] != NULL) {
     4422        InsertGraphIntoGraph(out, *FragmentList, (*FragmentLowerOrdersList[RootNr][i]), &counter);
     4423        delete(FragmentLowerOrdersList[RootNr][i]);
     4424      }
     4425    }
     4426    Free((void **)&FragmentLowerOrdersList[RootNr], "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]");
     4427    RootNr++;
     4428  }
     4429  Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList");
     4430  Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder");
     4431
     4432  *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl;
    44334433};
    44344434
     
    44404440inline int CompareDoubles (const void * a, const void * b)
    44414441{
    4442         if (*(double *)a > *(double *)b)
    4443                 return -1;
    4444         else if (*(double *)a < *(double *)b)
    4445                 return 1;
    4446         else
    4447                 return 0;
     4442  if (*(double *)a > *(double *)b)
     4443    return -1;
     4444  else if (*(double *)a < *(double *)b)
     4445    return 1;
     4446  else
     4447    return 0;
    44484448};
    44494449
     
    44564456int * molecule::IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold)
    44574457{
    4458         int flag;
    4459         double *Distances = NULL, *OtherDistances = NULL;
    4460         Vector CenterOfGravity, OtherCenterOfGravity;
    4461         size_t *PermMap = NULL, *OtherPermMap = NULL;
    4462         int *PermutationMap = NULL;
    4463         atom *Walker = NULL;
    4464         bool result = true; // status of comparison
    4465 
    4466         *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl;
    4467         /// first count both their atoms and elements and update lists thereby ...
    4468         //*out << Verbose(0) << "Counting atoms, updating list" << endl;
    4469         CountAtoms(out);
    4470         OtherMolecule->CountAtoms(out);
    4471         CountElements();
    4472         OtherMolecule->CountElements();
    4473 
    4474         /// ... and compare:
    4475         /// -# AtomCount
    4476         if (result) {
    4477                 if (AtomCount != OtherMolecule->AtomCount) {
    4478                         *out << Verbose(4) << "AtomCounts don't match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl;
    4479                         result = false;
    4480                 } else *out << Verbose(4) << "AtomCounts match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl;
    4481         }
    4482         /// -# ElementCount
    4483         if (result) {
    4484                 if (ElementCount != OtherMolecule->ElementCount) {
    4485                         *out << Verbose(4) << "ElementCount don't match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;
    4486                         result = false;
    4487                 } else *out << Verbose(4) << "ElementCount match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;
    4488         }
    4489         /// -# ElementsInMolecule
    4490         if (result) {
    4491                 for (flag=MAX_ELEMENTS;flag--;) {
    4492                         //*out << Verbose(5) << "Element " <<   flag << ": " << ElementsInMolecule[flag] << " <-> " << OtherMolecule->ElementsInMolecule[flag] << "." << endl;
    4493                         if (ElementsInMolecule[flag] != OtherMolecule->ElementsInMolecule[flag])
    4494                                 break;
    4495                 }
    4496                 if (flag < MAX_ELEMENTS) {
    4497                         *out << Verbose(4) << "ElementsInMolecule don't match." << endl;
    4498                         result = false;
    4499                 } else *out << Verbose(4) << "ElementsInMolecule match." << endl;
    4500         }
    4501         /// then determine and compare center of gravity for each molecule ...
    4502         if (result) {
    4503                 *out << Verbose(5) << "Calculating Centers of Gravity" << endl;
    4504                 DeterminePeriodicCenter(CenterOfGravity);
    4505                 OtherMolecule->DeterminePeriodicCenter(OtherCenterOfGravity);
    4506                 *out << Verbose(5) << "Center of Gravity: ";
    4507                 CenterOfGravity.Output(out);
    4508                 *out << endl << Verbose(5) << "Other Center of Gravity: ";
    4509                 OtherCenterOfGravity.Output(out);
    4510                 *out << endl;
    4511                 if (CenterOfGravity.DistanceSquared(&OtherCenterOfGravity) > threshold*threshold) {
    4512                         *out << Verbose(4) << "Centers of gravity don't match." << endl;
    4513                         result = false;
    4514                 }
    4515         }
    4516 
    4517         /// ... then make a list with the euclidian distance to this center for each atom of both molecules
    4518         if (result) {
    4519                 *out << Verbose(5) << "Calculating distances" << endl;
    4520                 Distances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: Distances");
    4521                 OtherDistances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: OtherDistances");
    4522                 Walker = start;
    4523                 while (Walker->next != end) {
    4524                         Walker = Walker->next;
    4525                         Distances[Walker->nr] = CenterOfGravity.DistanceSquared(&Walker->x);
    4526                 }
    4527                 Walker = OtherMolecule->start;
    4528                 while (Walker->next != OtherMolecule->end) {
    4529                         Walker = Walker->next;
    4530                         OtherDistances[Walker->nr] = OtherCenterOfGravity.DistanceSquared(&Walker->x);
    4531                 }
    4532 
    4533                 /// ... sort each list (using heapsort (o(N log N)) from GSL)
    4534                 *out << Verbose(5) << "Sorting distances" << endl;
    4535                 PermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermMap");
    4536                 OtherPermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *OtherPermMap");
    4537                 gsl_heapsort_index (PermMap, Distances, AtomCount, sizeof(double), CompareDoubles);
    4538                 gsl_heapsort_index (OtherPermMap, OtherDistances, AtomCount, sizeof(double), CompareDoubles);
    4539                 PermutationMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermutationMap");
    4540                 *out << Verbose(5) << "Combining Permutation Maps" << endl;
    4541                 for(int i=AtomCount;i--;)
    4542                         PermutationMap[PermMap[i]] = (int) OtherPermMap[i];
    4543 
    4544                 /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all
    4545                 *out << Verbose(4) << "Comparing distances" << endl;
    4546                 flag = 0;
    4547                 for (int i=0;i<AtomCount;i++) {
    4548                         *out << Verbose(5) << "Distances squared: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " <<      threshold << endl;
    4549                         if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) > threshold*threshold)
    4550                                 flag = 1;
    4551                 }
    4552                 Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap");
    4553                 Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap");
    4554 
    4555                 /// free memory
    4556                 Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances");
    4557                 Free((void **)&OtherDistances, "molecule::IsEqualToWithinThreshold: OtherDistances");
    4558                 if (flag) { // if not equal
    4559                         Free((void **)&PermutationMap, "molecule::IsEqualToWithinThreshold: *PermutationMap");
    4560                         result = false;
    4561                 }
    4562         }
    4563         /// return pointer to map if all distances were below \a threshold
    4564         *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl;
    4565         if (result) {
    4566                 *out << Verbose(3) << "Result: Equal." << endl;
    4567                 return PermutationMap;
    4568         } else {
    4569                 *out << Verbose(3) << "Result: Not equal." << endl;
    4570                 return NULL;
    4571         }
     4458  int flag;
     4459  double *Distances = NULL, *OtherDistances = NULL;
     4460  Vector CenterOfGravity, OtherCenterOfGravity;
     4461  size_t *PermMap = NULL, *OtherPermMap = NULL;
     4462  int *PermutationMap = NULL;
     4463  atom *Walker = NULL;
     4464  bool result = true; // status of comparison
     4465
     4466  *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl;
     4467  /// first count both their atoms and elements and update lists thereby ...
     4468  //*out << Verbose(0) << "Counting atoms, updating list" << endl;
     4469  CountAtoms(out);
     4470  OtherMolecule->CountAtoms(out);
     4471  CountElements();
     4472  OtherMolecule->CountElements();
     4473
     4474  /// ... and compare:
     4475  /// -# AtomCount
     4476  if (result) {
     4477    if (AtomCount != OtherMolecule->AtomCount) {
     4478      *out << Verbose(4) << "AtomCounts don't match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl;
     4479      result = false;
     4480    } else *out << Verbose(4) << "AtomCounts match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl;
     4481  }
     4482  /// -# ElementCount
     4483  if (result) {
     4484    if (ElementCount != OtherMolecule->ElementCount) {
     4485      *out << Verbose(4) << "ElementCount don't match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;
     4486      result = false;
     4487    } else *out << Verbose(4) << "ElementCount match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;
     4488  }
     4489  /// -# ElementsInMolecule
     4490  if (result) {
     4491    for (flag=MAX_ELEMENTS;flag--;) {
     4492      //*out << Verbose(5) << "Element " <<  flag << ": " << ElementsInMolecule[flag] << " <-> " << OtherMolecule->ElementsInMolecule[flag] << "." << endl;
     4493      if (ElementsInMolecule[flag] != OtherMolecule->ElementsInMolecule[flag])
     4494        break;
     4495    }
     4496    if (flag < MAX_ELEMENTS) {
     4497      *out << Verbose(4) << "ElementsInMolecule don't match." << endl;
     4498      result = false;
     4499    } else *out << Verbose(4) << "ElementsInMolecule match." << endl;
     4500  }
     4501  /// then determine and compare center of gravity for each molecule ...
     4502  if (result) {
     4503    *out << Verbose(5) << "Calculating Centers of Gravity" << endl;
     4504    DeterminePeriodicCenter(CenterOfGravity);
     4505    OtherMolecule->DeterminePeriodicCenter(OtherCenterOfGravity);
     4506    *out << Verbose(5) << "Center of Gravity: ";
     4507    CenterOfGravity.Output(out);
     4508    *out << endl << Verbose(5) << "Other Center of Gravity: ";
     4509    OtherCenterOfGravity.Output(out);
     4510    *out << endl;
     4511    if (CenterOfGravity.DistanceSquared(&OtherCenterOfGravity) > threshold*threshold) {
     4512      *out << Verbose(4) << "Centers of gravity don't match." << endl;
     4513      result = false;
     4514    }
     4515  }
     4516
     4517  /// ... then make a list with the euclidian distance to this center for each atom of both molecules
     4518  if (result) {
     4519    *out << Verbose(5) << "Calculating distances" << endl;
     4520    Distances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: Distances");
     4521    OtherDistances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: OtherDistances");
     4522    Walker = start;
     4523    while (Walker->next != end) {
     4524      Walker = Walker->next;
     4525      Distances[Walker->nr] = CenterOfGravity.DistanceSquared(&Walker->x);
     4526    }
     4527    Walker = OtherMolecule->start;
     4528    while (Walker->next != OtherMolecule->end) {
     4529      Walker = Walker->next;
     4530      OtherDistances[Walker->nr] = OtherCenterOfGravity.DistanceSquared(&Walker->x);
     4531    }
     4532
     4533    /// ... sort each list (using heapsort (o(N log N)) from GSL)
     4534    *out << Verbose(5) << "Sorting distances" << endl;
     4535    PermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermMap");
     4536    OtherPermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *OtherPermMap");
     4537    gsl_heapsort_index (PermMap, Distances, AtomCount, sizeof(double), CompareDoubles);
     4538    gsl_heapsort_index (OtherPermMap, OtherDistances, AtomCount, sizeof(double), CompareDoubles);
     4539    PermutationMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermutationMap");
     4540    *out << Verbose(5) << "Combining Permutation Maps" << endl;
     4541    for(int i=AtomCount;i--;)
     4542      PermutationMap[PermMap[i]] = (int) OtherPermMap[i];
     4543
     4544    /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all
     4545    *out << Verbose(4) << "Comparing distances" << endl;
     4546    flag = 0;
     4547    for (int i=0;i<AtomCount;i++) {
     4548      *out << Verbose(5) << "Distances squared: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " <<  threshold << endl;
     4549      if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) > threshold*threshold)
     4550        flag = 1;
     4551    }
     4552    Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap");
     4553    Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap");
     4554
     4555    /// free memory
     4556    Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances");
     4557    Free((void **)&OtherDistances, "molecule::IsEqualToWithinThreshold: OtherDistances");
     4558    if (flag) { // if not equal
     4559      Free((void **)&PermutationMap, "molecule::IsEqualToWithinThreshold: *PermutationMap");
     4560      result = false;
     4561    }
     4562  }
     4563  /// return pointer to map if all distances were below \a threshold
     4564  *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl;
     4565  if (result) {
     4566    *out << Verbose(3) << "Result: Equal." << endl;
     4567    return PermutationMap;
     4568  } else {
     4569    *out << Verbose(3) << "Result: Not equal." << endl;
     4570    return NULL;
     4571  }
    45724572};
    45734573
     
    45814581int * molecule::GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule)
    45824582{
    4583         atom *Walker = NULL, *OtherWalker = NULL;
    4584         *out << Verbose(3) << "Begin of GetFatherAtomicMap." << endl;
    4585         int *AtomicMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::GetAtomicMap: *AtomicMap");   //Calloc
    4586         for (int i=AtomCount;i--;)
    4587                 AtomicMap[i] = -1;
    4588         if (OtherMolecule == this) {    // same molecule
    4589                 for (int i=AtomCount;i--;) // no need as -1 means already that there is trivial correspondence
    4590                         AtomicMap[i] = i;
    4591                 *out << Verbose(4) << "Map is trivial." << endl;
    4592         } else {
    4593                 *out << Verbose(4) << "Map is ";
    4594                 Walker = start;
    4595                 while (Walker->next != end) {
    4596                         Walker = Walker->next;
    4597                         if (Walker->father == NULL) {
    4598                                 AtomicMap[Walker->nr] = -2;
    4599                         } else {
    4600                                 OtherWalker = OtherMolecule->start;
    4601                                 while (OtherWalker->next != OtherMolecule->end) {
    4602                                         OtherWalker = OtherWalker->next;
    4603                         //for (int i=0;i<AtomCount;i++) { // search atom
    4604                                 //for (int j=0;j<OtherMolecule->AtomCount;j++) {
    4605                                         //*out << Verbose(4) << "Comparing father " << Walker->father << " with the other one " << OtherWalker->father << "." << endl;
    4606                                         if (Walker->father == OtherWalker)
    4607                                                 AtomicMap[Walker->nr] = OtherWalker->nr;
    4608                                 }
    4609                         }
    4610                         *out << AtomicMap[Walker->nr] << "\t";
    4611                 }
    4612                 *out << endl;
    4613         }
    4614         *out << Verbose(3) << "End of GetFatherAtomicMap." << endl;
    4615         return AtomicMap;
     4583  atom *Walker = NULL, *OtherWalker = NULL;
     4584  *out << Verbose(3) << "Begin of GetFatherAtomicMap." << endl;
     4585  int *AtomicMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::GetAtomicMap: *AtomicMap");  //Calloc
     4586  for (int i=AtomCount;i--;)
     4587    AtomicMap[i] = -1;
     4588  if (OtherMolecule == this) {  // same molecule
     4589    for (int i=AtomCount;i--;) // no need as -1 means already that there is trivial correspondence
     4590      AtomicMap[i] = i;
     4591    *out << Verbose(4) << "Map is trivial." << endl;
     4592  } else {
     4593    *out << Verbose(4) << "Map is ";
     4594    Walker = start;
     4595    while (Walker->next != end) {
     4596      Walker = Walker->next;
     4597      if (Walker->father == NULL) {
     4598        AtomicMap[Walker->nr] = -2;
     4599      } else {
     4600        OtherWalker = OtherMolecule->start;
     4601        while (OtherWalker->next != OtherMolecule->end) {
     4602          OtherWalker = OtherWalker->next;
     4603      //for (int i=0;i<AtomCount;i++) { // search atom
     4604        //for (int j=0;j<OtherMolecule->AtomCount;j++) {
     4605          //*out << Verbose(4) << "Comparing father " << Walker->father << " with the other one " << OtherWalker->father << "." << endl;
     4606          if (Walker->father == OtherWalker)
     4607            AtomicMap[Walker->nr] = OtherWalker->nr;
     4608        }
     4609      }
     4610      *out << AtomicMap[Walker->nr] << "\t";
     4611    }
     4612    *out << endl;
     4613  }
     4614  *out << Verbose(3) << "End of GetFatherAtomicMap." << endl;
     4615  return AtomicMap;
    46164616};
    46174617
     
    46274627bool molecule::OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output)
    46284628{
    4629         double temperature;
    4630         atom *Walker = NULL;
    4631         // test stream
    4632         if (output == NULL)
    4633                 return false;
    4634         else
    4635                 *output << "# Step Temperature [K] Temperature [a.u.]" << endl;
    4636         for (int step=startstep;step < endstep; step++) { // loop over all time steps
    4637                 temperature = 0.;
    4638                 Walker = start;
    4639                 while (Walker->next != end) {
    4640                         Walker = Walker->next;
    4641                         for (int i=NDIM;i--;)
    4642                                 temperature += Walker->type->mass * Trajectories[Walker].U.at(step).x[i]* Trajectories[Walker].U.at(step).x[i];
    4643                 }
    4644                 *output << step << "\t" << temperature*AtomicEnergyToKelvin << "\t" << temperature << endl;
    4645         }
    4646         return true;
    4647 };
     4629  double temperature;
     4630  atom *Walker = NULL;
     4631  // test stream
     4632  if (output == NULL)
     4633    return false;
     4634  else
     4635    *output << "# Step Temperature [K] Temperature [a.u.]" << endl;
     4636  for (int step=startstep;step < endstep; step++) { // loop over all time steps
     4637    temperature = 0.;
     4638    Walker = start;
     4639    while (Walker->next != end) {
     4640      Walker = Walker->next;
     4641      for (int i=NDIM;i--;)
     4642        temperature += Walker->type->mass * Trajectories[Walker].U.at(step).x[i]* Trajectories[Walker].U.at(step).x[i];
     4643    }
     4644    *output << step << "\t" << temperature*AtomicEnergyToKelvin << "\t" << temperature << endl;
     4645  }
     4646  return true;
     4647};
  • src/molecules.hpp

    r178f92 r437922  
    7676struct KeyCompare
    7777{
    78         bool operator() (const KeySet SubgraphA, const KeySet SubgraphB) const;
     78  bool operator() (const KeySet SubgraphA, const KeySet SubgraphB) const;
    7979};
    8080
    8181struct Trajectory
    8282{
    83         vector<Vector> R;       //!< position vector
    84         vector<Vector> U;       //!< velocity vector
    85         vector<Vector> F;       //!< last force vector
    86         atom *ptr;                              //!< pointer to atom whose trajectory we contain
    87 };
    88 
    89 //bool operator < (KeySet SubgraphA, KeySet SubgraphB);  //note: this declaration is important, otherwise normal < is used (producing wrong order)
     83  vector<Vector> R;  //!< position vector
     84  vector<Vector> U;  //!< velocity vector
     85  vector<Vector> F;  //!< last force vector
     86  atom *ptr;        //!< pointer to atom whose trajectory we contain
     87};
     88
     89//bool operator < (KeySet SubgraphA, KeySet SubgraphB);  //note: this declaration is important, otherwise normal < is used (producing wrong order)
    9090inline void InsertFragmentIntoGraph(ofstream *out, struct UniqueFragments *Fragment); // Insert a KeySet into a Graph
    91 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter);    // Insert all KeySet's in a Graph into another Graph
     91inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter);  // Insert all KeySet's in a Graph into another Graph
    9292int CompareDoubles (const void * a, const void * b);
    9393
     
    9797
    9898// some algebraic matrix stuff
    99 #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
    100 #define RDET2(a0,a1,a2,a3) ((a0)*(a3)-(a1)*(a2))                                                                                        //!< hard-coded determinant of a 2x2 matrix
     99#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
     100#define RDET2(a0,a1,a2,a3) ((a0)*(a3)-(a1)*(a2))                      //!< hard-coded determinant of a 2x2 matrix
    101101
    102102
     
    104104 */
    105105struct LSQ_params {
    106         Vector **vectors;
    107         int num;
     106  Vector **vectors;
     107  int num;
    108108};
    109109
     
    113113 */
    114114struct lsq_params {
    115         gsl_vector *x;
    116         const molecule *mol;
    117         element *type;
     115  gsl_vector *x;
     116  const molecule *mol;
     117  element *type;
    118118};
    119119
     
    122122 */
    123123class atom {
    124         public:
    125                 Vector x;                        //!< coordinate array of atom, giving position within cell
    126                 Vector v;                        //!< velocity array of atom
    127                 element *type;  //!< pointing to element
    128                 atom *previous; //!< previous atom in molecule list
    129                 atom *next;              //!< next atom in molecule list
    130                 atom *father;    //!< In many-body bond order fragmentations points to originating atom
    131                 atom *Ancestor; //!< "Father" in Depth-First-Search
    132                 char *Name;                     //!< unique name used during many-body bond-order fragmentation
    133                 int FixedIon;    //!< config variable that states whether forces act on the ion or not
    134                 int *sort;                      //!< sort criteria
    135                 int nr;                          //!< continuous, unique number
    136                 int GraphNr;                    //!< unique number, given in DepthFirstSearchAnalysis()
    137                 int *ComponentNr;//!< belongs to this nonseparable components, given in DepthFirstSearchAnalysis() (if more than one, then is SeparationVertex)
    138                 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.
    139                 bool SeparationVertex; //!< whether this atom separates off subsets of atoms or not, determined in DepthFirstSearchAnalysis()
    140                 bool IsCyclic;                          //!< whether atom belong to as cycle or not, determined in DepthFirstSearchAnalysis()
    141                 unsigned char AdaptiveOrder;    //!< current present bond order at site (0 means "not set")
    142                 bool MaxOrder;  //!< whether this atom as a root in fragmentation still creates more fragments on higher orders or not
    143 
    144         atom();
    145         ~atom();
    146 
    147         bool Output(int ElementNo, int AtomNo, ofstream *out, const char *comment = NULL) const;
    148         bool OutputXYZLine(ofstream *out) const;
    149         atom *GetTrueFather();
    150         bool Compare(atom &ptr);
    151 
    152         private:
     124  public:
     125    Vector x;      //!< coordinate array of atom, giving position within cell
     126    Vector v;      //!< velocity array of atom
     127    element *type;  //!< pointing to element
     128    atom *previous; //!< previous atom in molecule list
     129    atom *next;    //!< next atom in molecule list
     130    atom *father;  //!< In many-body bond order fragmentations points to originating atom
     131    atom *Ancestor; //!< "Father" in Depth-First-Search
     132    char *Name;      //!< unique name used during many-body bond-order fragmentation
     133    int FixedIon;  //!< config variable that states whether forces act on the ion or not
     134    int *sort;      //!< sort criteria
     135    int nr;        //!< continuous, unique number
     136    int GraphNr;      //!< unique number, given in DepthFirstSearchAnalysis()
     137    int *ComponentNr;//!< belongs to this nonseparable components, given in DepthFirstSearchAnalysis() (if more than one, then is SeparationVertex)
     138    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.
     139    bool SeparationVertex; //!< whether this atom separates off subsets of atoms or not, determined in DepthFirstSearchAnalysis()
     140    bool IsCyclic;        //!< whether atom belong to as cycle or not, determined in DepthFirstSearchAnalysis()
     141    unsigned char AdaptiveOrder;  //!< current present bond order at site (0 means "not set")
     142    bool MaxOrder;  //!< whether this atom as a root in fragmentation still creates more fragments on higher orders or not
     143
     144  atom();
     145  ~atom();
     146
     147  bool Output(int ElementNo, int AtomNo, ofstream *out, const char *comment = NULL) const;
     148  bool OutputXYZLine(ofstream *out) const;
     149  atom *GetTrueFather();
     150  bool Compare(atom &ptr);
     151
     152  private:
    153153};
    154154
     
    161161 */
    162162class bond {
    163         public:
    164                 atom *leftatom;         //!< first bond partner
    165                 atom *rightatom;        //!< second bond partner
    166                 bond *previous; //!< previous atom in molecule list
    167                 bond *next;              //!< next atom in molecule list
    168                 int HydrogenBond;       //!< Number of hydrogen atoms in the bond
    169                 int BondDegree;         //!< single, double, triple, ... bond
    170                 int nr;                                  //!< unique number in a molecule, updated by molecule::CreateAdjacencyList()
    171                 bool Cyclic;                    //!< flag whether bond is part of a cycle or not, given in DepthFirstSearchAnalysis()
    172                 enum EdgeType Type;//!< whether this is a tree or back edge
    173 
    174         atom * GetOtherAtom(atom *Atom) const;
    175         bond * GetFirstBond();
    176         bond * GetLastBond();
    177 
    178         bool MarkUsed(enum Shading color);
    179         enum Shading IsUsed();
    180         void ResetUsed();
    181         bool Contains(const atom *ptr);
    182         bool Contains(const int nr);
    183 
    184         bond();
    185         bond(atom *left, atom *right);
    186         bond(atom *left, atom *right, int degree);
    187         bond(atom *left, atom *right, int degree, int number);
    188         ~bond();
    189 
    190         private:
    191                 enum Shading Used;                              //!< marker in depth-first search, DepthFirstSearchAnalysis()
     163  public:
     164    atom *leftatom;    //!< first bond partner
     165    atom *rightatom;  //!< second bond partner
     166    bond *previous; //!< previous atom in molecule list
     167    bond *next;    //!< next atom in molecule list
     168    int HydrogenBond;  //!< Number of hydrogen atoms in the bond
     169    int BondDegree;    //!< single, double, triple, ... bond
     170    int nr;          //!< unique number in a molecule, updated by molecule::CreateAdjacencyList()
     171    bool Cyclic;      //!< flag whether bond is part of a cycle or not, given in DepthFirstSearchAnalysis()
     172    enum EdgeType Type;//!< whether this is a tree or back edge
     173
     174  atom * GetOtherAtom(atom *Atom) const;
     175  bond * GetFirstBond();
     176  bond * GetLastBond();
     177
     178  bool MarkUsed(enum Shading color);
     179  enum Shading IsUsed();
     180  void ResetUsed();
     181  bool Contains(const atom *ptr);
     182  bool Contains(const int nr);
     183
     184  bond();
     185  bond(atom *left, atom *right);
     186  bond(atom *left, atom *right, int degree);
     187  bond(atom *left, atom *right, int degree, int number);
     188  ~bond();
     189
     190  private:
     191    enum Shading Used;        //!< marker in depth-first search, DepthFirstSearchAnalysis()
    192192};
    193193
     
    200200 */
    201201class molecule {
    202         public:
    203                 double cell_size[6];//!< cell size
    204                 periodentafel *elemente; //!< periodic table with each element
    205                 atom *start;                            //!< start of atom list
    206                 atom *end;                                      //!< end of atom list
    207                 bond *first;                            //!< start of bond list
    208                 bond *last;                              //!< end of bond list
    209                 bond ***ListOfBondsPerAtom; //!< pointer list for each atom and each bond it has
    210                 map<atom *, struct Trajectory> Trajectories; //!< contains old trajectory points
    211                 int MDSteps;                            //!< The number of MD steps in Trajectories
    212                 int *NumberOfBondsPerAtom;      //!< Number of Bonds each atom has
    213                 int AtomCount;                                  //!< number of atoms, brought up-to-date by CountAtoms()
    214                 int BondCount;                                  //!< number of atoms, brought up-to-date by CountBonds()
    215                 int ElementCount;                        //!< how many unique elements are therein
    216                 int ElementsInMolecule[MAX_ELEMENTS]; //!< list whether element (sorted by atomic number) is alread present or not
    217                 int NoNonHydrogen;      //!< number of non-hydrogen atoms in molecule
    218                 int NoNonBonds;          //!< number of non-hydrogen bonds in molecule
    219                 int NoCyclicBonds;      //!< number of cyclic bonds in molecule, by DepthFirstSearchAnalysis()
    220                 double BondDistance;    //!< typical bond distance used in CreateAdjacencyList() and furtheron
    221                 bool ActiveFlag;    //!< in a MoleculeListClass used to discern active from inactive molecules
    222                 Vector Center;      //!< Center of molecule in a global box
    223                 char name[MAXSTRINGSIZE];         //!< arbitrary name
    224                 int IndexNr;        //!< index of molecule in a MoleculeListClass
    225 
    226         molecule(periodentafel *teil);
    227         ~molecule();
    228 
    229         /// remove atoms from molecule.
    230         bool AddAtom(atom *pointer);
    231         bool RemoveAtom(atom *pointer);
    232         bool UnlinkAtom(atom *pointer);
    233         bool CleanupMolecule();
    234 
    235         /// Add/remove atoms to/from molecule.
    236         atom * AddCopyAtom(atom *pointer);
    237         bool AddXYZFile(string filename);
    238         bool AddHydrogenReplacementAtom(ofstream *out, bond *Bond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem);
    239         bond * AddBond(atom *first, atom *second, int degree);
    240         bool RemoveBond(bond *pointer);
    241         bool RemoveBonds(atom *BondPartner);
    242 
    243         /// Find atoms.
    244         atom * FindAtom(int Nr) const;
    245         atom * AskAtom(string text);
    246 
    247         /// Count and change present atoms' coordination.
    248         void CountAtoms(ofstream *out);
    249         void CountElements();
    250         void CalculateOrbitals(class config &configuration);
    251         bool CenterInBox(ofstream *out, Vector *BoxLengths);
    252         void CenterEdge(ofstream *out, Vector *max);
    253         void CenterOrigin(ofstream *out);
    254         void CenterPeriodic(ofstream *out);
    255         void CenterAtVector(ofstream *out, Vector *newcenter);
    256         void Translate(const Vector *x);
    257         void Mirror(const Vector *x);
    258         void Align(Vector *n);
    259         void Scale(double **factor);
    260         void DeterminePeriodicCenter(Vector &center);
    261         Vector * DetermineCenterOfGravity(ofstream *out);
    262         Vector * DetermineCenterOfAll(ofstream *out);
    263         void SetNameFromFilename(const char *filename);
    264         void SetBoxDimension(Vector *dim);
    265         double * ReturnFullMatrixforSymmetric(double *cell_size);
    266         void ScanForPeriodicCorrection(ofstream *out);
    267         void PrincipalAxisSystem(ofstream *out, bool DoRotate);
    268         double VolumeOfConvexEnvelope(ofstream *out, bool IsAngstroem);
    269         Vector* FindEmbeddingHole(ofstream *out, molecule *srcmol);
    270 
    271         bool VerletForceIntegration(char *file, double delta_t, bool IsAngstroem);
    272 
    273         bool CheckBounds(const Vector *x) const;
    274         void GetAlignvector(struct lsq_params * par) const;
    275 
    276         /// Initialising routines in fragmentation
    277         void CreateAdjacencyList2(ofstream *out, ifstream *output);
    278         void CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem);
    279         void CreateListOfBondsPerAtom(ofstream *out);
    280 
    281         // Graph analysis
    282         MoleculeLeafClass * DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack);
    283         void CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> *BackEdgeStack, int *&MinimumRingSize);
    284         bool PickLocalBackEdges(ofstream *out, atom **ListOfLocalAtoms, class StackClass<bond *> *&ReferenceStack, class StackClass<bond *> *&LocalStack);
    285         bond * FindNextUnused(atom *vertex);
    286         void SetNextComponentNumber(atom *vertex, int nr);
    287         void InitComponentNumbers();
    288         void OutputComponentNumber(ofstream *out, atom *vertex);
    289         void ResetAllBondsToUnused();
    290         void ResetAllAtomNumbers();
    291         int CountCyclicBonds(ofstream *out);
    292         bool CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment);
    293         string GetColor(enum Shading color);
    294 
    295         molecule *CopyMolecule();
    296 
    297         /// Fragment molecule by two different approaches:
    298         int FragmentMolecule(ofstream *out, int Order, config *configuration);
    299         bool CheckOrderAtSite(ofstream *out, bool *AtomMask, Graph *GlobalKeySetList, int Order, int *MinimumRingSize, char *path = NULL);
    300         bool StoreAdjacencyToFile(ofstream *out, char *path);
    301         bool CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms);
    302         bool ParseOrderAtSiteFromFile(ofstream *out, char *path);
    303         bool StoreOrderAtSiteFile(ofstream *out, char *path);
    304         bool ParseKeySetFile(ofstream *out, char *filename, Graph *&FragmentList);
    305         bool StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path);
    306         bool StoreForcesFile(ofstream *out, MoleculeListClass *BondFragments, char *path, int *SortIndex);
    307         bool CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex);
    308         bool ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet);
    309         void BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem);
    310         /// -# BOSSANOVA
    311         void FragmentBOSSANOVA(ofstream *out, Graph *&FragmentList, KeyStack &RootStack, int *MinimumRingSize);
    312         int PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet);
    313         bool BuildInducedSubgraph(ofstream *out, const molecule *Father);
    314         molecule * StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem);
    315         void SPFragmentGenerator(ofstream *out, struct UniqueFragments *FragmentSearch, int RootDistance, bond **BondsSet, int SetDimension, int SubOrder);
    316         int LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList);
    317         int GuesstimateFragmentCount(ofstream *out, int order);
    318 
    319         // Recognize doubly appearing molecules in a list of them
    320         int * IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold);
    321         int * GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule);
    322 
    323         // Output routines.
    324         bool Output(ofstream *out);
    325         bool OutputTrajectories(ofstream *out);
    326         void OutputListOfBonds(ofstream *out) const;
    327         bool OutputXYZ(ofstream *out) const;
    328         bool OutputTrajectoriesXYZ(ofstream *out);
    329         bool Checkout(ofstream *out) const;
    330         bool OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output);
    331 
    332         private:
    333         int last_atom;                  //!< number given to last atom
     202  public:
     203    double cell_size[6];//!< cell size
     204    periodentafel *elemente; //!< periodic table with each element
     205    atom *start;        //!< start of atom list
     206    atom *end;          //!< end of atom list
     207    bond *first;        //!< start of bond list
     208    bond *last;        //!< end of bond list
     209    bond ***ListOfBondsPerAtom; //!< pointer list for each atom and each bond it has
     210    map<atom *, struct Trajectory> Trajectories; //!< contains old trajectory points
     211    int MDSteps;        //!< The number of MD steps in Trajectories
     212    int *NumberOfBondsPerAtom;  //!< Number of Bonds each atom has
     213    int AtomCount;          //!< number of atoms, brought up-to-date by CountAtoms()
     214    int BondCount;          //!< number of atoms, brought up-to-date by CountBonds()
     215    int ElementCount;      //!< how many unique elements are therein
     216    int ElementsInMolecule[MAX_ELEMENTS]; //!< list whether element (sorted by atomic number) is alread present or not
     217    int NoNonHydrogen;  //!< number of non-hydrogen atoms in molecule
     218    int NoNonBonds;    //!< number of non-hydrogen bonds in molecule
     219    int NoCyclicBonds;  //!< number of cyclic bonds in molecule, by DepthFirstSearchAnalysis()
     220    double BondDistance;  //!< typical bond distance used in CreateAdjacencyList() and furtheron
     221    bool ActiveFlag;    //!< in a MoleculeListClass used to discern active from inactive molecules
     222    Vector Center;      //!< Center of molecule in a global box
     223    char name[MAXSTRINGSIZE];         //!< arbitrary name
     224    int IndexNr;        //!< index of molecule in a MoleculeListClass
     225
     226  molecule(periodentafel *teil);
     227  ~molecule();
     228
     229  /// remove atoms from molecule.
     230  bool AddAtom(atom *pointer);
     231  bool RemoveAtom(atom *pointer);
     232  bool UnlinkAtom(atom *pointer);
     233  bool CleanupMolecule();
     234
     235  /// Add/remove atoms to/from molecule.
     236  atom * AddCopyAtom(atom *pointer);
     237  bool AddXYZFile(string filename);
     238  bool AddHydrogenReplacementAtom(ofstream *out, bond *Bond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem);
     239  bond * AddBond(atom *first, atom *second, int degree);
     240  bool RemoveBond(bond *pointer);
     241  bool RemoveBonds(atom *BondPartner);
     242
     243  /// Find atoms.
     244  atom * FindAtom(int Nr) const;
     245  atom * AskAtom(string text);
     246
     247  /// Count and change present atoms' coordination.
     248  void CountAtoms(ofstream *out);
     249  void CountElements();
     250  void CalculateOrbitals(class config &configuration);
     251  bool CenterInBox(ofstream *out, Vector *BoxLengths);
     252  void CenterEdge(ofstream *out, Vector *max);
     253  void CenterOrigin(ofstream *out);
     254  void CenterPeriodic(ofstream *out);
     255  void CenterAtVector(ofstream *out, Vector *newcenter);
     256  void Translate(const Vector *x);
     257  void Mirror(const Vector *x);
     258  void Align(Vector *n);
     259  void Scale(double **factor);
     260  void DeterminePeriodicCenter(Vector &center);
     261  Vector * DetermineCenterOfGravity(ofstream *out);
     262  Vector * DetermineCenterOfAll(ofstream *out);
     263  void SetNameFromFilename(const char *filename);
     264  void SetBoxDimension(Vector *dim);
     265  double * ReturnFullMatrixforSymmetric(double *cell_size);
     266  void ScanForPeriodicCorrection(ofstream *out);
     267  void PrincipalAxisSystem(ofstream *out, bool DoRotate);
     268  double VolumeOfConvexEnvelope(ofstream *out, bool IsAngstroem);
     269  Vector* FindEmbeddingHole(ofstream *out, molecule *srcmol);
     270
     271  bool VerletForceIntegration(char *file, double delta_t, bool IsAngstroem);
     272
     273  bool CheckBounds(const Vector *x) const;
     274  void GetAlignvector(struct lsq_params * par) const;
     275
     276  /// Initialising routines in fragmentation
     277  void CreateAdjacencyList2(ofstream *out, ifstream *output);
     278  void CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem);
     279  void CreateListOfBondsPerAtom(ofstream *out);
     280
     281  // Graph analysis
     282  MoleculeLeafClass * DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack);
     283  void CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> *BackEdgeStack, int *&MinimumRingSize);
     284  bool PickLocalBackEdges(ofstream *out, atom **ListOfLocalAtoms, class StackClass<bond *> *&ReferenceStack, class StackClass<bond *> *&LocalStack);
     285  bond * FindNextUnused(atom *vertex);
     286  void SetNextComponentNumber(atom *vertex, int nr);
     287  void InitComponentNumbers();
     288  void OutputComponentNumber(ofstream *out, atom *vertex);
     289  void ResetAllBondsToUnused();
     290  void ResetAllAtomNumbers();
     291  int CountCyclicBonds(ofstream *out);
     292  bool CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment);
     293  string GetColor(enum Shading color);
     294
     295  molecule *CopyMolecule();
     296
     297  /// Fragment molecule by two different approaches:
     298  int FragmentMolecule(ofstream *out, int Order, config *configuration);
     299  bool CheckOrderAtSite(ofstream *out, bool *AtomMask, Graph *GlobalKeySetList, int Order, int *MinimumRingSize, char *path = NULL);
     300  bool StoreAdjacencyToFile(ofstream *out, char *path);
     301  bool CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms);
     302  bool ParseOrderAtSiteFromFile(ofstream *out, char *path);
     303  bool StoreOrderAtSiteFile(ofstream *out, char *path);
     304  bool ParseKeySetFile(ofstream *out, char *filename, Graph *&FragmentList);
     305  bool StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path);
     306  bool StoreForcesFile(ofstream *out, MoleculeListClass *BondFragments, char *path, int *SortIndex);
     307  bool CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex);
     308  bool ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet);
     309  void BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem);
     310  /// -# BOSSANOVA
     311  void FragmentBOSSANOVA(ofstream *out, Graph *&FragmentList, KeyStack &RootStack, int *MinimumRingSize);
     312  int PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet);
     313  bool BuildInducedSubgraph(ofstream *out, const molecule *Father);
     314  molecule * StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem);
     315  void SPFragmentGenerator(ofstream *out, struct UniqueFragments *FragmentSearch, int RootDistance, bond **BondsSet, int SetDimension, int SubOrder);
     316  int LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList);
     317  int GuesstimateFragmentCount(ofstream *out, int order);
     318
     319  // Recognize doubly appearing molecules in a list of them
     320  int * IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold);
     321  int * GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule);
     322
     323  // Output routines.
     324  bool Output(ofstream *out);
     325  bool OutputTrajectories(ofstream *out);
     326  void OutputListOfBonds(ofstream *out) const;
     327  bool OutputXYZ(ofstream *out) const;
     328  bool OutputTrajectoriesXYZ(ofstream *out);
     329  bool Checkout(ofstream *out) const;
     330  bool OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output);
     331
     332  private:
     333  int last_atom;      //!< number given to last atom
    334334};
    335335
     
    337337 */
    338338class MoleculeListClass {
    339         public:
    340           MoleculeList ListOfMolecules; //!< List of the contained molecules
    341           int MaxIndex;
    342 
    343         MoleculeListClass();
    344         ~MoleculeListClass();
    345 
    346         bool AddHydrogenCorrection(ofstream *out, char *path);
    347         bool StoreForcesFile(ofstream *out, char *path, int *SortIndex);
    348         void insert(molecule *mol);
    349         molecule * ReturnIndex(int index);
    350         bool OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex);
    351         int NumberOfActiveMolecules();
    352         void Enumerate(ofstream *out);
    353         void Output(ofstream *out);
    354 
    355         // merging of molecules
     339  public:
     340    MoleculeList ListOfMolecules; //!< List of the contained molecules
     341    int MaxIndex;
     342
     343  MoleculeListClass();
     344  ~MoleculeListClass();
     345
     346  bool AddHydrogenCorrection(ofstream *out, char *path);
     347  bool StoreForcesFile(ofstream *out, char *path, int *SortIndex);
     348  void insert(molecule *mol);
     349  molecule * ReturnIndex(int index);
     350  bool OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex);
     351  int NumberOfActiveMolecules();
     352  void Enumerate(ofstream *out);
     353  void Output(ofstream *out);
     354
     355  // merging of molecules
    356356  bool SimpleMerge(molecule *mol, molecule *srcmol);
    357357  bool SimpleAdd(molecule *mol, molecule *srcmol);
     
    361361  bool EmbedMerge(molecule *mol, molecule *srcmol);
    362362
    363         private:
     363  private:
    364364};
    365365
     
    369369 */
    370370class MoleculeLeafClass {
    371         public:
    372                 molecule *Leaf;                                                                  //!< molecule of this leaf
    373                 //MoleculeLeafClass *UpLeaf;                            //!< Leaf one level up
    374                 //MoleculeLeafClass *DownLeaf;                  //!< First leaf one level down
    375                 MoleculeLeafClass *previous;    //!< Previous leaf on this level
    376                 MoleculeLeafClass *next;                        //!< Next leaf on this level
    377 
    378         //MoleculeLeafClass(MoleculeLeafClass *Up, MoleculeLeafClass *Previous);
    379         MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf);
    380         ~MoleculeLeafClass();
    381 
    382         bool AddLeaf(molecule *ptr, MoleculeLeafClass *Previous);
    383         bool FillBondStructureFromReference(ofstream *out, molecule *reference, int &FragmentCounter, atom ***&ListOfLocalAtoms, bool FreeList = false);
    384         bool FillRootStackForSubgraphs(ofstream *out, KeyStack *&RootStack, bool *AtomMask, int &FragmentCounter);
    385         bool AssignKeySetsToFragment(ofstream *out, molecule *reference, Graph *KeySetList, atom ***&ListOfLocalAtoms, Graph **&FragmentList, int &FragmentCounter, bool FreeList = false);
    386         bool FillListOfLocalAtoms(ofstream *out, atom ***&ListOfLocalAtoms, const int FragmentCounter, const int GlobalAtomCount, bool &FreeList);
    387         void TranslateIndicesToGlobalIDs(ofstream *out, Graph **FragmentList, int &FragmentCounter, int &TotalNumberOfKeySets, Graph &TotalGraph);
    388         int Count() const;
     371  public:
     372    molecule *Leaf;                  //!< molecule of this leaf
     373    //MoleculeLeafClass *UpLeaf;        //!< Leaf one level up
     374    //MoleculeLeafClass *DownLeaf;      //!< First leaf one level down
     375    MoleculeLeafClass *previous;  //!< Previous leaf on this level
     376    MoleculeLeafClass *next;      //!< Next leaf on this level
     377
     378  //MoleculeLeafClass(MoleculeLeafClass *Up, MoleculeLeafClass *Previous);
     379  MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf);
     380  ~MoleculeLeafClass();
     381
     382  bool AddLeaf(molecule *ptr, MoleculeLeafClass *Previous);
     383  bool FillBondStructureFromReference(ofstream *out, molecule *reference, int &FragmentCounter, atom ***&ListOfLocalAtoms, bool FreeList = false);
     384  bool FillRootStackForSubgraphs(ofstream *out, KeyStack *&RootStack, bool *AtomMask, int &FragmentCounter);
     385  bool AssignKeySetsToFragment(ofstream *out, molecule *reference, Graph *KeySetList, atom ***&ListOfLocalAtoms, Graph **&FragmentList, int &FragmentCounter, bool FreeList = false);
     386  bool FillListOfLocalAtoms(ofstream *out, atom ***&ListOfLocalAtoms, const int FragmentCounter, const int GlobalAtomCount, bool &FreeList);
     387  void TranslateIndicesToGlobalIDs(ofstream *out, Graph **FragmentList, int &FragmentCounter, int &TotalNumberOfKeySets, Graph &TotalGraph);
     388  int Count() const;
    389389};
    390390
     
    393393 */
    394394class config {
    395         public:
    396                 int PsiType;
    397                 int MaxPsiDouble;
    398                 int PsiMaxNoUp;
    399                 int PsiMaxNoDown;
    400                 int MaxMinStopStep;
    401                 int InitMaxMinStopStep;
    402                 int ProcPEGamma;
    403                 int ProcPEPsi;
    404                 char *configpath;
    405                 char *configname;
    406                 bool FastParsing;
    407                 double Deltat;
    408                 string basis;
    409 
    410                 private:
    411                 char *mainname;
    412                 char *defaultpath;
    413                 char *pseudopotpath;
    414 
    415                 int DoOutVis;
    416                 int DoOutMes;
    417                 int DoOutNICS;
    418                 int DoOutOrbitals;
    419                 int DoOutCurrent;
    420                 int DoFullCurrent;
    421                 int DoPerturbation;
    422                 int DoWannier;
    423                 int CommonWannier;
    424                 double SawtoothStart;
    425                 int VectorPlane;
    426                 double VectorCut;
    427                 int UseAddGramSch;
    428                 int Seed;
    429 
    430                 int MaxOuterStep;
    431                 int OutVisStep;
    432                 int OutSrcStep;
    433                 double TargetTemp;
    434                 int ScaleTempStep;
    435                 int MaxPsiStep;
    436                 double EpsWannier;
    437 
    438                 int MaxMinStep;
    439                 double RelEpsTotalEnergy;
    440                 double RelEpsKineticEnergy;
    441                 int MaxMinGapStopStep;
    442                 int MaxInitMinStep;
    443                 double InitRelEpsTotalEnergy;
    444                 double InitRelEpsKineticEnergy;
    445                 int InitMaxMinGapStopStep;
    446 
    447                 //double BoxLength[NDIM*NDIM];
    448 
    449                 double ECut;
    450                 int MaxLevel;
    451                 int RiemannTensor;
    452                 int LevRFactor;
    453                 int RiemannLevel;
    454                 int Lev0Factor;
    455                 int RTActualUse;
    456                 int AddPsis;
    457 
    458                 double RCut;
    459                 int StructOpt;
    460                 int IsAngstroem;
    461                 int RelativeCoord;
    462                 int MaxTypes;
    463 
    464 
    465         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);
    466 
    467         public:
    468         config();
    469         ~config();
    470 
    471         int TestSyntax(char *filename, periodentafel *periode, molecule *mol);
    472         void Load(char *filename, periodentafel *periode, molecule *mol);
    473         void LoadOld(char *filename, periodentafel *periode, molecule *mol);
    474         void RetrieveConfigPathAndName(string filename);
    475         bool Save(const char *filename, periodentafel *periode, molecule *mol) const;
    476         bool SaveMPQC(const char *filename, molecule *mol) const;
    477         void Edit();
    478         bool GetIsAngstroem() const;
    479         char *GetDefaultPath() const;
    480         void SetDefaultPath(const char *path);
     395  public:
     396    int PsiType;
     397    int MaxPsiDouble;
     398    int PsiMaxNoUp;
     399    int PsiMaxNoDown;
     400    int MaxMinStopStep;
     401    int InitMaxMinStopStep;
     402    int ProcPEGamma;
     403    int ProcPEPsi;
     404    char *configpath;
     405    char *configname;
     406    bool FastParsing;
     407    double Deltat;
     408    string basis;
     409
     410    private:
     411    char *mainname;
     412    char *defaultpath;
     413    char *pseudopotpath;
     414
     415    int DoOutVis;
     416    int DoOutMes;
     417    int DoOutNICS;
     418    int DoOutOrbitals;
     419    int DoOutCurrent;
     420    int DoFullCurrent;
     421    int DoPerturbation;
     422    int DoWannier;
     423    int CommonWannier;
     424    double SawtoothStart;
     425    int VectorPlane;
     426    double VectorCut;
     427    int UseAddGramSch;
     428    int Seed;
     429
     430    int MaxOuterStep;
     431    int OutVisStep;
     432    int OutSrcStep;
     433    double TargetTemp;
     434    int ScaleTempStep;
     435    int MaxPsiStep;
     436    double EpsWannier;
     437
     438    int MaxMinStep;
     439    double RelEpsTotalEnergy;
     440    double RelEpsKineticEnergy;
     441    int MaxMinGapStopStep;
     442    int MaxInitMinStep;
     443    double InitRelEpsTotalEnergy;
     444    double InitRelEpsKineticEnergy;
     445    int InitMaxMinGapStopStep;
     446
     447    //double BoxLength[NDIM*NDIM];
     448
     449    double ECut;
     450    int MaxLevel;
     451    int RiemannTensor;
     452    int LevRFactor;
     453    int RiemannLevel;
     454    int Lev0Factor;
     455    int RTActualUse;
     456    int AddPsis;
     457
     458    double RCut;
     459    int StructOpt;
     460    int IsAngstroem;
     461    int RelativeCoord;
     462    int MaxTypes;
     463
     464
     465  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);
     466
     467  public:
     468  config();
     469  ~config();
     470
     471  int TestSyntax(char *filename, periodentafel *periode, molecule *mol);
     472  void Load(char *filename, periodentafel *periode, molecule *mol);
     473  void LoadOld(char *filename, periodentafel *periode, molecule *mol);
     474  void RetrieveConfigPathAndName(string filename);
     475  bool Save(const char *filename, periodentafel *periode, molecule *mol) const;
     476  bool SaveMPQC(const char *filename, molecule *mol) const;
     477  void Edit();
     478  bool GetIsAngstroem() const;
     479  char *GetDefaultPath() const;
     480  void SetDefaultPath(const char *path);
    481481};
    482482
  • src/parser.cpp

    r178f92 r437922  
    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
     
    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
     
    193193 * -# First, count the number of matrices by counting lines in KEYSETFILE
    194194 * -# 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
     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
    202202 * -# Finally, allocate one additional matrix (\a MatrixCounter) containing combined or temporary values
    203203 * \param *name directory with files
     
    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
     
    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
     
    473473bool EnergyMatrix::ParseIndices()
    474474{
    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;
     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
     
    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
     
    550550bool ForceMatrix::ParseIndices(char *name)
    551551{
    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;
     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
     
    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

    r178f92 r437922  
    4040
    4141class MatrixContainer {
    42         public:
    43                 double ***Matrix;
    44                 int **Indices;
    45                 char *Header;
    46                 int MatrixCounter;
    47                 int *RowCounter;
    48                 int ColumnCounter;
     42  public:
     43    double ***Matrix;
     44    int **Indices;
     45    char *Header;
     46    int MatrixCounter;
     47    int *RowCounter;
     48    int ColumnCounter;
    4949
    50         MatrixContainer();
    51         virtual ~MatrixContainer();
     50  MatrixContainer();
     51  virtual ~MatrixContainer();
    5252
    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);
     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);
    6666};
    6767
     
    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;
     89  public:
     90    int **KeySets;
     91    int *AtomCounter;
     92    int FragmentCounter;
     93    int Order;
     94    int *FragmentsPerOrder;
     95    int **OrderSet;
    9696
    97         KeySetsContainer();
    98         ~KeySetsContainer();
     97  KeySetsContainer();
     98  ~KeySetsContainer();
    9999
    100         bool ParseKeySets(const char *name, const int *ACounter, const int FCounter);
    101         bool ParseManyBodyTerms();
    102         bool Contains(const int GreaterSet, const int SmallerSet);
     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

    r178f92 r437922  
    1616periodentafel::periodentafel()
    1717{
    18         start = new element;
    19         end = new element;
    20         start->previous = NULL;
    21         start->next = end;
    22         end->previous = start;
    23         end->next = NULL;
     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
     
    2929periodentafel::~periodentafel()
    3030{
    31         CleanupPeriodtable();
    32         delete(end);
    33         delete(start);
     31  CleanupPeriodtable();
     32  delete(end);
     33  delete(start);
    3434};
    3535
     
    4040bool periodentafel::AddElement(element *pointer)
    4141{
    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);
     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
     
    5252bool periodentafel::RemoveElement(element *pointer)
    5353{
    54         return remove(pointer, start, end);
     54  return remove(pointer, start, end);
    5555};
    5656
     
    6060bool periodentafel::CleanupPeriodtable()
    6161{
    62         return cleanup(start,end);
     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
     
    107107element * periodentafel::AskElement()
    108108{
    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;
     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;
    117117};
    118118
     
    122122bool periodentafel::Output(ofstream *output) const
    123123{
    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;
     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;
    134134};
    135135
     
    140140bool periodentafel::Checkout(ofstream *output, const int *checkliste) const
    141141{
    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;
     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;
    159159};
    160160
     
    164164bool periodentafel::LoadPeriodentafel(char *path)
    165165{
    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;
     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;
    299299};
    300300
     
    303303bool periodentafel::StorePeriodentafel(char *path) const
    304304{
    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 };
     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};
Note: See TracChangeset for help on using the changeset viewer.