Changes in / [375b458:51c910]


Ignore:
Location:
src
Files:
1 added
22 edited

Legend:

Unmodified
Added
Removed
  • src/Makefile.am

    r375b458 r51c910  
    1010
    1111
    12 #EXTRA_DIST = ${molecuilder_DATA}
     12EXTRA_DIST = ${molecuilder_DATA}
  • src/analyzer.cpp

    r375b458 r51c910  
    2323int main(int argc, char **argv)
    2424{
    25         periodentafel *periode = NULL; // and a period table of all elements
    26         EnergyMatrix Energy;
    27         EnergyMatrix Hcorrection;
    28         ForceMatrix Force;
    29         ForceMatrix Shielding;
    30         ForceMatrix ShieldingPAS;
    31         EnergyMatrix Time;
    32         EnergyMatrix EnergyFragments;
    33         EnergyMatrix HcorrectionFragments;
    34         ForceMatrix ForceFragments;
    35         ForceMatrix ShieldingFragments;
    36         ForceMatrix ShieldingPASFragments;
    37         KeySetsContainer KeySet;
    38         ofstream output;
    39         ofstream output2;
    40         ofstream output3;
    41         ofstream output4;
    42         ifstream input;
    43         stringstream filename;
    44         time_t t = time(NULL);
    45         struct tm *ts = localtime(&t);
    46         char *datum = asctime(ts);
    47         stringstream Orderxrange;
    48         stringstream Fragmentxrange;
    49         stringstream yrange;
    50         char *dir = NULL;
    51         bool Hcorrected = true;
    52         double norm;
    53         int counter;
    54 
    55         cout << "ANOVA Analyzer" << endl;
    56         cout << "==============" << endl;
    57 
    58         // Get the command line options
    59         if (argc < 4) {
    60                 cout << "Usage: " << argv[0] << " <inputdir> <prefix> <outputdir> [elementsdb]" << endl;
    61                 cout << "<inputdir>\ttherein the output of a molecuilder fragmentation is expected, each fragment with a subdir containing an energy.all and a forces.all file." << endl;
    62                 cout << "<prefix>\tprefix of energy and forces file." << endl;
    63                 cout << "<outputdir>\tcreated plotfiles and datafiles are placed into this directory " << endl;
    64                 cout << "[elementsdb]\tpath to elements database, needed for shieldings." << endl;
    65                 return 1;
    66         } else {
    67                 dir = (char *) Malloc(sizeof(char)*(strlen(argv[2])+2), "main: *dir");
    68                 strcpy(dir, "/");
    69                 strcat(dir, argv[2]);
    70         }
    71 
    72         if (argc > 4) {
    73                 cout << "Loading periodentafel." << endl;
    74                 periode = new periodentafel;
    75                 periode->LoadPeriodentafel(argv[4]);
    76         }
    77 
    78         // Test the given directory
    79         if (!TestParams(argc, argv))
    80                 return 1;
    81 
    82         // +++++++++++++++++ PARSING +++++++++++++++++++++++++++++++
    83 
    84         // ------------- Parse through all Fragment subdirs --------
    85         if (!Energy.ParseFragmentMatrix(argv[1], dir, EnergySuffix,0,0)) return 1;
    86         Hcorrected = Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX,0,0);
    87         if (!Force.ParseFragmentMatrix(argv[1], dir, ForcesSuffix,0,0)) return 1;
    88         if (!Time.ParseFragmentMatrix(argv[1], dir, TimeSuffix, 10,1)) return 1;
    89         if (periode != NULL) { // also look for PAS values
    90                 if (!Shielding.ParseFragmentMatrix(argv[1], dir, ShieldingSuffix, 1, 0)) return 1;
    91                 if (!ShieldingPAS.ParseFragmentMatrix(argv[1], dir, ShieldingPASSuffix, 1, 0)) return 1;
    92         }
    93 
    94         // ---------- Parse the TE Factors into an array -----------------
    95         if (!Energy.ParseIndices()) return 1;
    96         if (Hcorrected) Hcorrection.ParseIndices();
    97 
    98         // ---------- Parse the Force indices into an array ---------------
    99         if (!Force.ParseIndices(argv[1])) return 1;
    100         if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return 1;
    101         if (!ForceFragments.ParseIndices(argv[1])) return 1;
    102 
    103         // ---------- Parse the shielding indices into an array ---------------
    104         if (periode != NULL) { // also look for PAS values
    105                 if(!Shielding.ParseIndices(argv[1])) return 1;
    106                 if(!ShieldingPAS.ParseIndices(argv[1])) return 1;
    107                 if (!ShieldingFragments.AllocateMatrix(Shielding.Header, Shielding.MatrixCounter, Shielding.RowCounter, Shielding.ColumnCounter)) return 1;
    108                 if (!ShieldingPASFragments.AllocateMatrix(ShieldingPAS.Header, ShieldingPAS.MatrixCounter, ShieldingPAS.RowCounter, ShieldingPAS.ColumnCounter)) return 1;
    109                 if(!ShieldingFragments.ParseIndices(argv[1])) return 1;
    110                 if(!ShieldingPASFragments.ParseIndices(argv[1])) return 1;
    111         }
    112 
    113         // ---------- Parse the KeySets into an array ---------------
    114         if (!KeySet.ParseKeySets(argv[1], Force.RowCounter, Force.MatrixCounter)) return 1;
    115         if (!KeySet.ParseManyBodyTerms()) return 1;
    116 
    117         // ---------- Parse fragment files created by 'joiner' into an array -------------
    118         if (!EnergyFragments.ParseFragmentMatrix(argv[1], dir, EnergyFragmentSuffix,0,0)) return 1;
    119         if (Hcorrected) HcorrectionFragments.ParseFragmentMatrix(argv[1], dir, HcorrectionFragmentSuffix,0,0);
    120         if (!ForceFragments.ParseFragmentMatrix(argv[1], dir, ForceFragmentSuffix,0,0)) return 1;
    121         if (periode != NULL) { // also look for PAS values
    122                 if (!ShieldingFragments.ParseFragmentMatrix(argv[1], dir, ShieldingFragmentSuffix, 1, 0)) return 1;
    123                 if (!ShieldingPASFragments.ParseFragmentMatrix(argv[1], dir, ShieldingPASFragmentSuffix, 1, 0)) return 1;
    124         }
    125 
    126         // +++++++++++++++ TESTING ++++++++++++++++++++++++++++++
    127 
    128         // print energy and forces to file
    129         filename.str("");
    130         filename << argv[3] << "/" << "energy-forces.all";
    131         output.open(filename.str().c_str(), ios::out);
    132         output << endl << "Total Energy" << endl << "==============" << endl << Energy.Header << endl;
    133         for(int j=0;j<Energy.RowCounter[Energy.MatrixCounter];j++) {
    134                 for(int k=0;k<Energy.ColumnCounter;k++)
    135                         output << scientific << Energy.Matrix[ Energy.MatrixCounter ][j][k] << "\t";
    136                 output << endl;
    137         }
    138         output << endl;
    139 
    140         output << endl << "Total Forces" << endl << "===============" << endl << Force.Header << endl;
    141         for(int j=0;j<Force.RowCounter[Force.MatrixCounter];j++) {
    142                 for(int k=0;k<Force.ColumnCounter;k++)
    143                         output << scientific << Force.Matrix[ Force.MatrixCounter ][j][k] << "\t";
    144                 output << endl;
    145         }
    146         output << endl;
    147 
    148         if (periode != NULL) { // also look for PAS values
    149                 output << endl << "Total Shieldings" << endl << "===============" << endl << Shielding.Header << endl;
    150                 for(int j=0;j<Shielding.RowCounter[Shielding.MatrixCounter];j++) {
    151                         for(int k=0;k<Shielding.ColumnCounter;k++)
    152                                 output << scientific << Shielding.Matrix[ Shielding.MatrixCounter ][j][k] << "\t";
    153                         output << endl;
    154                 }
    155                 output << endl;
    156 
    157                 output << endl << "Total Shieldings PAS" << endl << "===============" << endl << ShieldingPAS.Header << endl;
    158                 for(int j=0;j<ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter];j++) {
    159                         for(int k=0;k<ShieldingPAS.ColumnCounter;k++)
    160                                 output << scientific << ShieldingPAS.Matrix[ ShieldingPAS.MatrixCounter ][j][k] << "\t";
    161                         output << endl;
    162                 }
    163                 output << endl;
    164         }
    165 
    166         output << endl << "Total Times" << endl << "===============" << endl << Time.Header << endl;
    167         for(int j=0;j<Time.RowCounter[Time.MatrixCounter];j++) {
    168                 for(int k=0;k<Time.ColumnCounter;k++) {
    169                         output << scientific << Time.Matrix[ Time.MatrixCounter ][j][k] << "\t";
    170                 }
    171                 output << endl;
    172         }
    173         output << endl;
    174         output.close();
    175         for(int k=0;k<Time.ColumnCounter;k++)
    176                 Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k] = Time.Matrix[ Time.MatrixCounter ][Time.RowCounter[Time.MatrixCounter]-1][k];
    177 
    178         // +++++++++++++++ ANALYZING ++++++++++++++++++++++++++++++
    179 
    180         cout << "Analyzing ..." << endl;
    181 
    182         // ======================================= Creating the data files ==============================================================
    183 
    184         // +++++++++++++++++++++++++++++++++++++++ Plotting Simtime vs Bond Order
    185         // +++++++++++++++++++++++++++++++++++++++ Plotting Delta Simtime vs Bond Order
    186         if (!OpenOutputFile(output, argv[3], "SimTime-Order.dat" )) return false;
    187         if (!OpenOutputFile(output2, argv[3], "DeltaSimTime-Order.dat" )) return false;
    188         for(int j=Time.RowCounter[Time.MatrixCounter];j--;)
    189                 for(int k=Time.ColumnCounter;k--;) {
    190                         Time.Matrix[ Time.MatrixCounter ][j][k] = 0.;
    191                 }
    192         counter = 0;
    193         output << "#Order\tFrag.No.\t" << Time.Header << endl;
    194         output2 << "#Order\tFrag.No.\t" << Time.Header << endl;
    195         for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
    196                 for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;)
    197                         for(int j=Time.RowCounter[Time.MatrixCounter];j--;)
    198                                 for(int k=Time.ColumnCounter;k--;) {
    199                                         Time.Matrix[ Time.MatrixCounter ][j][k] += Time.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
    200                                 }
    201                 counter += KeySet.FragmentsPerOrder[BondOrder];
    202                 output << BondOrder+1 << "\t" << counter;
    203                 output2 << BondOrder+1 << "\t" << counter;
    204                 for(int k=0;k<Time.ColumnCounter;k++) {
    205                         output << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k];
    206                         if (fabs(Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k]) > MYEPSILON)
    207                                 output2 << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k] / Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k];
    208                         else
    209                                 output2 << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k];
    210                 }
    211                 output << endl;
    212                 output2 << endl;
    213         }
    214         output.close();
    215         output2.close();
    216 
    217         // +++++++++++++++++++++++++++++++++++++++ Plotting shieldings
    218 
    219         if (periode != NULL) { // also look for PAS values
    220                 if (!CreateDataDeltaForcesOrderPerAtom(ShieldingPAS, ShieldingPASFragments, KeySet, argv[3], "DeltaShieldingsPAS-Order", "Plot of error between approximated shieldings and full shieldings versus the Bond Order", datum)) return 1;
    221                 if (!CreateDataForcesOrderPerAtom(ShieldingPASFragments, KeySet, argv[3], "ShieldingsPAS-Order", "Plot of approximated shieldings versus the Bond Order", datum)) return 1;
    222                 if (!AppendOutputFile(output, argv[3], "ShieldingsPAS-Order.dat" )) return false;
    223                 output << endl << "# Full" << endl;
    224                 for(int j=0;j<ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter];j++) {
    225                         output << j << "\t";
    226                         for(int k=0;k<ShieldingPAS.ColumnCounter;k++)
    227                                 output << scientific << ShieldingPAS.Matrix[ ShieldingPAS.MatrixCounter ][j][k] << "\t"; //*(((k>1) && (k<6))? 1.e6 : 1.) << "\t";
    228                         output << endl;
    229                 }
    230         }
    231         output.close();
    232 
    233 
    234         // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in energy to full QM
    235         if (!CreateDataDeltaEnergyOrder(Energy, EnergyFragments, KeySet, argv[3], "DeltaEnergies-Order", "Plot of error between approximated and full energies energies versus the Bond Order", datum)) return 1;
    236 
    237         // +++++++++++++++++++++++++++++++++++Plotting Energies vs. Order
    238         if (!CreateDataEnergyOrder(EnergyFragments, KeySet, argv[3], "Energies-Order", "Plot of approximated energies versus the Bond Order", datum)) return 1;
    239 
    240         // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in forces to full QM
    241         if (!CreateDataDeltaForcesOrderPerAtom(Force, ForceFragments, KeySet, argv[3], "DeltaForces-Order", "Plot of error between approximated forces and full forces versus the Bond Order", datum)) return 1;
    242 
    243         // min force
    244         if (!CreateDataDeltaForcesOrder(Force, ForceFragments, KeySet, argv[3], "DeltaMinForces-Order", "Plot of min error between approximated forces and full forces versus the Bond Order", datum, CreateMinimumForce)) return 1;
    245 
    246         // mean force
    247         if (!CreateDataDeltaForcesOrder(Force, ForceFragments, KeySet, argv[3], "DeltaMeanForces-Order", "Plot of mean error between approximated forces and full forces versus the Bond Order", datum, CreateMeanForce)) return 1;
    248 
    249         // max force
    250         if (!CreateDataDeltaForcesOrder(Force, ForceFragments, KeySet, argv[3], "DeltaMaxForces-Order", "Plot of max error between approximated forces and full forces versus the Bond Order", datum, CreateMaximumForce)) return 1;
    251 
    252         // ++++++++++++++++++++++++++++++++++++++Plotting Forces vs. Order
    253         if (!CreateDataForcesOrderPerAtom(ForceFragments, KeySet, argv[3], "Forces-Order", "Plot of approximated forces versus the Bond Order", datum)) return 1;
    254         if (!AppendOutputFile(output, argv[3], "Forces-Order.dat" )) return false;
    255         output << endl << "# Full" << endl;
    256         for(int j=0;j<Force.RowCounter[Force.MatrixCounter];j++) {
    257                 output << j << "\t";
    258                 for(int k=0;k<Force.ColumnCounter;k++)
    259                         output << scientific << Force.Matrix[ Force.MatrixCounter ][j][k] << "\t";
    260                 output << endl;
    261         }
    262         output.close();
    263         // min force
    264         if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MinForces-Order", "Plot of min approximated forces versus the Bond Order", datum, CreateMinimumForce)) return 1;
    265 
    266         // mean force
    267         if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MeanForces-Order", "Plot of mean approximated forces versus the Bond Order", datum, CreateMeanForce)) return 1;
    268 
    269         // max force
    270         if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MaxForces-Order", "Plot of max approximated forces versus the Bond Order", datum, CreateMaximumForce)) return 1;
    271 
    272         // ++++++++++++++++++++++++++++++++++++++Plotting vector sum (should be 0) vs. bond order
    273         if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "VectorSum-Order", "Plot of vector sum of the approximated forces versus the Bond Order", datum, CreateVectorSumForce)) return 1;
    274 
    275         // +++++++++++++++++++++++++++++++Plotting energyfragments vs. order
    276         if (!CreateDataFragment(EnergyFragments, KeySet, argv[3], "Energies-Fragment", "Plot of fragment energy versus the Fragment No", datum, CreateEnergy)) return 1;
    277         if (!CreateDataFragment(EnergyFragments, KeySet, argv[3], "Energies-FragmentOrder", "Plot of fragment energy of each Fragment No vs. Bond Order", datum, CreateEnergy)) return 1;
    278         if (!CreateDataFragmentOrder(EnergyFragments, KeySet, argv[3], "MaxEnergies-FragmentOrder", "Plot of maximum of fragment energy vs. Bond Order", datum, CreateMaxFragmentOrder)) return 1;
    279         if (!CreateDataFragmentOrder(EnergyFragments, KeySet, argv[3], "MinEnergies-FragmentOrder", "Plot of minimum of fragment energy vs. Bond Order", datum, CreateMinFragmentOrder)) return 1;
    280 
    281         // +++++++++++++++++++++++++++++++Ploting min/mean/max forces for each fragment
    282         // min force
    283         if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MinForces-Fragment", "Plot of min approximated forces versus the Fragment No", datum, CreateMinimumForce)) return 1;
    284 
    285         // mean force
    286         if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MeanForces-Fragment", "Plot of mean approximated forces versus the Fragment No", datum, CreateMeanForce)) return 1;
    287 
    288         // max force
    289         if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MaxForces-Fragment", "Plot of max approximated forces versus the Fragment No", datum, CreateMaximumForce)) return 1;
    290 
    291         // +++++++++++++++++++++++++++++++Ploting min/mean/max forces for each fragment per order
    292         // min force
    293         if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MinForces-FragmentOrder", "Plot of min approximated forces of each Fragment No vs. Bond Order", datum, CreateMinimumForce)) return 1;
    294 
    295         // mean force
    296         if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MeanForces-FragmentOrder", "Plot of mean approximated forces of each Fragment No vs. Bond Order", datum, CreateMeanForce)) return 1;
    297 
    298         // max force
    299         if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MaxForces-FragmentOrder", "Plot of max approximated forces of each Fragment No vs. Bond Order", datum, CreateMaximumForce)) return 1;
    300 
    301         // ======================================= Creating the plot files ==============================================================
    302 
    303         Orderxrange << "[1:" << KeySet.Order << "]";
    304         Fragmentxrange << "[0:" << KeySet.FragmentCounter+1 << "]";
    305         yrange.str("[1e-8:1e+1]");
    306 
    307         // +++++++++++++++++++++++++++++++++++++++ Plotting Simtime vs Bond Order
    308         if (!CreatePlotOrder(Time, KeySet, argv[3], "SimTime-Order", 1, "below", "y", "",       1, 1, "bond order k", "Evaluation time [s]", Orderxrange.str().c_str(), "", "1" , "with linespoints", EnergyPlotLine)) return 1;
    309 
    310         // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in energy to full QM
    311         if (!CreatePlotOrder(Energy, KeySet, argv[3], "DeltaEnergies-Order", 1, "outside", "y", "",     1, 1, "bond order k", "absolute error in energy [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsEnergyPlotLine)) return 1;
    312 
    313         // +++++++++++++++++++++++++++++++++++Plotting Energies vs. Order
    314         if (!CreatePlotOrder(Energy, KeySet, argv[3], "Energies-Order", 1, "outside", "", "",   1, 1, "bond order k", "approximate energy [Ht]", Orderxrange.str().c_str(), "", "1" , "with linespoints", EnergyPlotLine)) return 1;
    315 
    316         // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in forces to full QM
    317         yrange.str("[1e-8:1e+0]");
    318         // min force
    319         if (!CreatePlotOrder(Force, KeySet, argv[3], "DeltaMinForces-Order", 2, "top right", "y", "",   1, 1, "bond order k", "absolute error in min force [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;
    320 
    321         // mean force
    322         if (!CreatePlotOrder(Force, KeySet, argv[3], "DeltaMeanForces-Order", 2, "top right", "y", "",  1, 1, "bond order k", "absolute error in mean force [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsFirstForceValuePlotLine)) return 1;
    323 
    324         // max force
    325         if (!CreatePlotOrder(Force, KeySet, argv[3], "DeltaMaxForces-Order", 2, "top right", "y", "",   1, 1, "bond order k", "absolute error in max force [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;
    326 
    327         // min/mean/max comparison for total force
    328         if(!OpenOutputFile(output, argv[3], "DeltaMinMeanMaxTotalForce-Order.pyx")) return 1;
    329         CreatePlotHeader(output, "DeltaMinMeanMaxTotalForce-Order", 1, "bottom left", "y", NULL,        1, 1, "bond order k", "absolute error in total forces [Ht/a.u.]");
    330         output << "plot " << Orderxrange.str().c_str() << " [1e-8:1e+0] \\" << endl;
    331         output << "'DeltaMinForces-Order.dat' title 'minimum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints, \\" << endl;
    332         output << "'DeltaMeanForces-Order.dat' title 'mean' using 1:(abs($" << 8 << ")) with linespoints, \\" << endl;
    333         output << "'DeltaMaxForces-Order.dat' title 'maximum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints" << endl;
    334         output.close();
    335 
    336         // ++++++++++++++++++++++++++++++++++++++Plotting Forces vs. Order
    337         // min force
    338         if (!CreatePlotOrder(Force, KeySet, argv[3], "MinForces-Order", 2, "bottom right", "y", "",     1, 1, "bond order k", "absolute approximated min force [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;
    339 
    340         // mean force
    341         if (!CreatePlotOrder(Force, KeySet, argv[3], "MeanForces-Order", 2, "bottom right", "y", "",    1, 1, "bond order k", "absolute approximated mean force [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", AbsFirstForceValuePlotLine)) return 1;
    342 
    343         // max force
    344         if (!CreatePlotOrder(Force, KeySet, argv[3], "MaxForces-Order", 2, "bottom right", "y", "",     1, 1, "bond order k", "absolute approximated max force [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;
    345 
    346         // min/mean/max comparison for total force
    347         if(!OpenOutputFile(output, argv[3],"MinMeanMaxTotalForce-Order.pyx")) return 1;
    348         CreatePlotHeader(output, "MinMeanMaxTotalForce-Order", 1, "bottom left", "y", NULL, 1, 1, "bond order k", "absolute total force [Ht/a.u.]");
    349         output << "plot "<< Orderxrange.str().c_str() << " [1e-8:1e+0] \\" << endl;
    350         output << "'MinForces-Order.dat' title 'minimum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints, \\" << endl;
    351         output << "'MeanForces-Order.dat' title 'mean' using 1:(abs($" << 8 << ")) with linespoints, \\" << endl;
    352         output << "'MaxForces-Order.dat' title 'maximum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints" << endl;
    353         output.close();
    354 
    355         // ++++++++++++++++++++++++++++++++++++++Plotting vector sum vs. Order
    356 
    357         if (!CreatePlotOrder(Force, KeySet, argv[3], "VectorSum-Order", 2, "bottom right", "y" ,"", 1, 1, "bond order k", "vector sum of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;
    358 
    359         // +++++++++++++++++++++++++++++++Plotting energyfragments vs. order
    360         yrange.str("");
    361         yrange << "[" << EnergyFragments.FindMinValue() << ":" << EnergyFragments.FindMaxValue() << "]";
    362         if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "Energies-Fragment", 5, "below", "y", "", 1, 5, "fragment number", "Energies of each fragment [Ht]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with points", AbsEnergyPlotLine)) return 1;
    363         if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "Energies-FragmentOrder", 5, "below", "y", "", 1, 1, "bond order", "Energies of each fragment [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with points", AbsEnergyPlotLine)) return 1;
    364         if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "MaxEnergies-FragmentOrder", 5, "below", "y", "", 1, 1, "bond order", "Maximum fragment energy [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsEnergyPlotLine)) return 1;
    365         if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "MinEnergies-FragmentOrder", 5, "below", "y", "", 1, 1, "bond order", "Minimum fragment energy [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsEnergyPlotLine)) return 1;
    366 
    367         // +++++++++++++++++++++++++++++++=Ploting min/mean/max forces for each fragment
    368         yrange.str("");
    369         yrange << "[" << ForceFragments.FindMinValue() << ":" << ForceFragments.FindMaxValue()<< "]";
    370         // min
    371         if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MinForces-Fragment", 5, "below", "y", "set boxwidth 0.2", 1, 5, "fragment number", "minimum of approximated forces [Ht/a.u.]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with boxes fillcolor", BoxesForcePlotLine)) return 1;
    372 
    373         // mean
    374         if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MeanForces-Fragment", 5, "below", "y", "set boxwidth 0.2", 1, 5, "fragment number", "mean of approximated forces [Ht/a.u.]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with boxes fillcolor", BoxesFirstForceValuePlotLine)) return 1;
    375 
    376         // max
    377         if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MaxForces-Fragment", 5, "below", "y", "set boxwidth 0.2", 1, 5, "fragment number", "maximum of approximated forces [Ht/a.u.]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with boxes fillcolor", BoxesForcePlotLine)) return 1;
    378 
    379         // +++++++++++++++++++++++++++++++=Ploting min/mean/max forces for each fragment per bond order
    380         // min
    381         if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MinForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "minimum of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesForcePlotLine)) return 1;
    382 
    383         // mean
    384         if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MeanForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "mean of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesFirstForceValuePlotLine)) return 1;
    385 
    386         // max
    387         if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MaxForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "maximum of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesForcePlotLine)) return 1;
    388 
    389         // +++++++++++++++++++++++++++++++=Ploting approximated and true shielding for each atom
    390         if (periode != NULL) { // also look for PAS values
    391                 if(!OpenOutputFile(output, argv[3], "ShieldingsPAS-Order.pyx")) return 1;
    392                 if(!OpenOutputFile(output2, argv[3], "DeltaShieldingsPAS-Order.pyx")) return 1;
    393                 CreatePlotHeader(output, "ShieldingsPAS-Order", 1, "top right", NULL, NULL,     1, 5, "nuclei index", "iso chemical shielding value [ppm]");
    394                 CreatePlotHeader(output2, "DeltaShieldingsPAS-Order", 1, "top right", NULL, NULL,       1, 5, "nuclei index", "iso chemical shielding value [ppm]");
    395                 double step=0.8/KeySet.Order;
    396                 output << "set boxwidth " << step << endl;
    397                 output << "plot [0:" << ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter]+10 << "]\\" << endl;
    398                 output2 << "plot [0:" << ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter]+10 << "]\\" << endl;
    399                 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
    400                         output << "'ShieldingsPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1+" << step*(double)BondOrder << "):7 with boxes, \\" << endl;
    401                         output2 << "'DeltaShieldingsPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1):7 with linespoints";
    402                         if (BondOrder-1 != KeySet.Order)
    403                                 output2 << ", \\" << endl;
    404                 }
    405                 output << "'ShieldingsPAS-Order.dat' index " << KeySet.Order << " title 'Full' using ($1+" << step*(double)KeySet.Order << "):7 with boxes" << endl;
    406                 output.close();
    407                 output2.close();
    408         }
    409 
    410         // create Makefile
    411         if(!OpenOutputFile(output, argv[3], "Makefile")) return 1;
    412         output << "PYX = $(shell ls *.pyx)" << endl << endl;
    413         output << "EPS = $(PYX:.pyx=.eps)" << endl << endl;
    414         output << "%.eps: %.pyx" << endl;
    415         output << "\t~/build/pyxplot/pyxplot $<" << endl << endl;
    416         output << "all: $(EPS)" << endl << endl;
    417         output << ".PHONY: clean" << endl;
    418         output << "clean:" << endl;
    419         output << "\trm -rf $(EPS)" << endl;
    420         output.close();
    421 
    422         // ++++++++++++++++ exit ++++++++++++++++++++++++++++++++++
    423         delete(periode);
    424         Free((void **)&dir, "main: *dir");
    425         cout << "done." << endl;
    426         return 0;
     25  periodentafel *periode = NULL; // and a period table of all elements
     26  EnergyMatrix Energy;
     27  EnergyMatrix EnergyFragments;
     28  ForceMatrix Force;
     29  ForceMatrix ForceFragments;
     30  HessianMatrix Hessian;
     31  HessianMatrix HessianFragments;
     32  EnergyMatrix Hcorrection;
     33  EnergyMatrix HcorrectionFragments;
     34  ForceMatrix Shielding;
     35  ForceMatrix ShieldingPAS;
     36  ForceMatrix Chi;
     37  ForceMatrix ChiPAS;
     38  EnergyMatrix Time;
     39  ForceMatrix ShieldingFragments;
     40  ForceMatrix ShieldingPASFragments;
     41  ForceMatrix ChiFragments;
     42  ForceMatrix ChiPASFragments;
     43  KeySetsContainer KeySet;
     44  ofstream output;
     45  ofstream output2;
     46  ofstream output3;
     47  ofstream output4;
     48  ifstream input;
     49  stringstream filename;
     50  time_t t = time(NULL);
     51  struct tm *ts = localtime(&t);
     52  char *datum = asctime(ts);
     53  stringstream Orderxrange;
     54  stringstream Fragmentxrange;
     55  stringstream yrange;
     56  char *dir = NULL;
     57  bool NoHessian = false;
     58  bool NoTime = false;
     59  bool NoHCorrection = true;
     60  int counter;
     61
     62  cout << "ANOVA Analyzer" << endl;
     63  cout << "==============" << endl;
     64
     65  // Get the command line options
     66  if (argc < 4) {
     67    cout << "Usage: " << argv[0] << " <inputdir> <prefix> <outputdir> [elementsdb]" << endl;
     68    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;
     69    cout << "<prefix>\tprefix of energy and forces file." << endl;
     70    cout << "<outputdir>\tcreated plotfiles and datafiles are placed into this directory " << endl;
     71    cout << "[elementsdb]\tpath to elements database, needed for shieldings." << endl;
     72    return 1;
     73  } else {
     74    dir = (char *) Malloc(sizeof(char)*(strlen(argv[2])+2), "main: *dir");
     75    strcpy(dir, "/");
     76    strcat(dir, argv[2]);
     77  }
     78
     79  if (argc > 4) {
     80    cout << "Loading periodentafel." << endl;
     81    periode = new periodentafel;
     82    periode->LoadPeriodentafel(argv[4]);
     83  }
     84
     85  // Test the given directory
     86  if (!TestParams(argc, argv))
     87    return 1;
     88
     89  // +++++++++++++++++ PARSING +++++++++++++++++++++++++++++++
     90
     91  // ------------- Parse through all Fragment subdirs --------
     92  if (!Energy.ParseFragmentMatrix(argv[1], dir, EnergySuffix,0,0)) return 1;
     93  if (!Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX,0,0)) {
     94    NoHCorrection = true;
     95    cout << "No HCorrection file found, skipping these." << endl;
     96  }
     97 
     98  if (!Force.ParseFragmentMatrix(argv[1], dir, ForcesSuffix,0,0)) return 1;
     99  if (!Hessian.ParseFragmentMatrix(argv[1], dir, HessianSuffix,0,0)) {
     100    NoHessian = true;
     101    cout << "No Hessian file found, skipping these." << endl;
     102  }
     103  if (!Time.ParseFragmentMatrix(argv[1], dir, TimeSuffix, 10,1)) {
     104    NoTime = true;
     105    cout << "No speed file found, skipping these." << endl;
     106  }
     107  if (periode != NULL) { // also look for PAS values
     108    if (!Shielding.ParseFragmentMatrix(argv[1], dir, ShieldingSuffix, 1, 0)) return 1;
     109    if (!ShieldingPAS.ParseFragmentMatrix(argv[1], dir, ShieldingPASSuffix, 1, 0)) return 1;
     110    if (!Chi.ParseFragmentMatrix(argv[1], dir, ChiSuffix, 1, 0)) return 1;
     111    if (!ChiPAS.ParseFragmentMatrix(argv[1], dir, ChiPASSuffix, 1, 0)) return 1;
     112  }
     113
     114  // ---------- Parse the TE Factors into an array -----------------
     115  if (!Energy.ParseIndices()) return 1;
     116  if (!NoHCorrection) Hcorrection.ParseIndices();
     117
     118  // ---------- Parse the Force indices into an array ---------------
     119  if (!Force.ParseIndices(argv[1])) return 1;
     120  if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return 1;
     121  if (!ForceFragments.InitialiseIndices((class MatrixContainer *)&Force)) return 1;
     122
     123  // ---------- Parse hessian indices into an array -----------------
     124  if (!NoHessian) {
     125    if (!Hessian.InitialiseIndices((class MatrixContainer *)&Force)) return 1;
     126    if (!HessianFragments.AllocateMatrix(Hessian.Header, Hessian.MatrixCounter, Hessian.RowCounter, Hessian.ColumnCounter)) return 1;
     127    if (!HessianFragments.InitialiseIndices((class MatrixContainer *)&Force)) return 1;
     128  }
     129
     130  // ---------- Parse the shielding indices into an array ---------------
     131  if (periode != NULL) { // also look for PAS values
     132    if(!Shielding.ParseIndices(argv[1])) return 1;
     133    if(!ShieldingPAS.ParseIndices(argv[1])) return 1;
     134    if (!ShieldingFragments.AllocateMatrix(Shielding.Header, Shielding.MatrixCounter, Shielding.RowCounter, Shielding.ColumnCounter)) return 1;
     135    if (!ShieldingPASFragments.AllocateMatrix(ShieldingPAS.Header, ShieldingPAS.MatrixCounter, ShieldingPAS.RowCounter, ShieldingPAS.ColumnCounter)) return 1;
     136    if(!ShieldingFragments.ParseIndices(argv[1])) return 1;
     137    if(!ShieldingPASFragments.ParseIndices(argv[1])) return 1;
     138    if(!Chi.ParseIndices(argv[1])) return 1;
     139    if(!ChiPAS.ParseIndices(argv[1])) return 1;
     140    if (!ChiFragments.AllocateMatrix(Chi.Header, Chi.MatrixCounter, Chi.RowCounter, Chi.ColumnCounter)) return 1;
     141    if (!ChiPASFragments.AllocateMatrix(ChiPAS.Header, ChiPAS.MatrixCounter, ChiPAS.RowCounter, ChiPAS.ColumnCounter)) return 1;
     142    if(!ChiFragments.ParseIndices(argv[1])) return 1;
     143    if(!ChiPASFragments.ParseIndices(argv[1])) return 1;
     144  }
     145
     146  // ---------- Parse the KeySets into an array ---------------
     147  if (!KeySet.ParseKeySets(argv[1], Force.RowCounter, Force.MatrixCounter)) return 1;
     148  if (!KeySet.ParseManyBodyTerms()) return 1;
     149
     150  // ---------- Parse fragment files created by 'joiner' into an array -------------
     151  if (!EnergyFragments.ParseFragmentMatrix(argv[1], dir, EnergyFragmentSuffix,0,0)) return 1;
     152  if (!NoHCorrection)
     153    HcorrectionFragments.ParseFragmentMatrix(argv[1], dir, HcorrectionFragmentSuffix,0,0);
     154  if (!ForceFragments.ParseFragmentMatrix(argv[1], dir, ForceFragmentSuffix,0,0)) return 1;
     155  if (!NoHessian)
     156    if (!HessianFragments.ParseFragmentMatrix(argv[1], dir, HessianFragmentSuffix,0,0)) return 1;
     157  if (periode != NULL) { // also look for PAS values
     158    if (!ShieldingFragments.ParseFragmentMatrix(argv[1], dir, ShieldingFragmentSuffix, 1, 0)) return 1;
     159    if (!ShieldingPASFragments.ParseFragmentMatrix(argv[1], dir, ShieldingPASFragmentSuffix, 1, 0)) return 1;
     160    if (!ChiFragments.ParseFragmentMatrix(argv[1], dir, ChiFragmentSuffix, 1, 0)) return 1;
     161    if (!ChiPASFragments.ParseFragmentMatrix(argv[1], dir, ChiPASFragmentSuffix, 1, 0)) return 1;
     162  }
     163
     164  // +++++++++++++++ TESTING ++++++++++++++++++++++++++++++
     165
     166  // print energy and forces to file
     167  filename.str("");
     168  filename << argv[3] << "/" << "energy-forces.all";
     169  output.open(filename.str().c_str(), ios::out);
     170  output << endl << "Total Energy" << endl << "==============" << endl << Energy.Header[Energy.MatrixCounter] << endl;
     171  for(int j=0;j<Energy.RowCounter[Energy.MatrixCounter];j++) {
     172    for(int k=0;k<Energy.ColumnCounter[Energy.MatrixCounter];k++)
     173      output << scientific << Energy.Matrix[ Energy.MatrixCounter ][j][k] << "\t";
     174    output << endl;
     175  }
     176  output << endl;
     177 
     178  output << endl << "Total Forces" << endl << "===============" << endl << Force.Header[Force.MatrixCounter] << endl;
     179  for(int j=0;j<Force.RowCounter[Force.MatrixCounter];j++) {
     180    for(int k=0;k<Force.ColumnCounter[Force.MatrixCounter];k++)
     181      output << scientific << Force.Matrix[ Force.MatrixCounter ][j][k] << "\t";
     182    output << endl;
     183  }
     184  output << endl;
     185
     186  if (!NoHessian) {
     187    output << endl << "Total Hessian" << endl << "===============" << endl << Hessian.Header[Hessian.MatrixCounter] << endl;
     188    for(int j=0;j<Hessian.RowCounter[Hessian.MatrixCounter];j++) {
     189      for(int k=0;k<Hessian.ColumnCounter[Hessian.MatrixCounter];k++)
     190        output << scientific << Hessian.Matrix[ Hessian.MatrixCounter ][j][k] << "\t";
     191      output << endl;
     192    }
     193    output << endl;
     194  }
     195
     196  if (periode != NULL) { // also look for PAS values
     197    output << endl << "Total Shieldings" << endl << "===============" << endl << Shielding.Header[Hessian.MatrixCounter] << endl;
     198    for(int j=0;j<Shielding.RowCounter[Shielding.MatrixCounter];j++) {
     199      for(int k=0;k<Shielding.ColumnCounter[Shielding.MatrixCounter];k++)
     200        output << scientific << Shielding.Matrix[ Shielding.MatrixCounter ][j][k] << "\t";
     201      output << endl;
     202    }
     203    output << endl;
     204 
     205    output << endl << "Total Shieldings PAS" << endl << "===============" << endl << ShieldingPAS.Header[ShieldingPAS.MatrixCounter] << endl;
     206    for(int j=0;j<ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter];j++) {
     207      for(int k=0;k<ShieldingPAS.ColumnCounter[ShieldingPAS.MatrixCounter];k++)
     208        output << scientific << ShieldingPAS.Matrix[ ShieldingPAS.MatrixCounter ][j][k] << "\t";
     209      output << endl;
     210    }
     211    output << endl;
     212
     213    output << endl << "Total Chis" << endl << "===============" << endl << Chi.Header[Chi.MatrixCounter] << endl;
     214    for(int j=0;j<Chi.RowCounter[Chi.MatrixCounter];j++) {
     215      for(int k=0;k<Chi.ColumnCounter[Chi.MatrixCounter];k++)
     216        output << scientific << Chi.Matrix[ Chi.MatrixCounter ][j][k] << "\t";
     217      output << endl;
     218    }
     219    output << endl;
     220 
     221    output << endl << "Total Chis PAS" << endl << "===============" << endl << ChiPAS.Header[ChiPAS.MatrixCounter] << endl;
     222    for(int j=0;j<ChiPAS.RowCounter[ChiPAS.MatrixCounter];j++) {
     223      for(int k=0;k<ChiPAS.ColumnCounter[ChiPAS.MatrixCounter];k++)
     224        output << scientific << ChiPAS.Matrix[ ChiPAS.MatrixCounter ][j][k] << "\t";
     225      output << endl;
     226    }
     227    output << endl;
     228  }
     229 
     230  if (!NoTime) {
     231    output << endl << "Total Times" << endl << "===============" << endl << Time.Header[Time.MatrixCounter] << endl;
     232    for(int j=0;j<Time.RowCounter[Time.MatrixCounter];j++) {
     233      for(int k=0;k<Time.ColumnCounter[Time.MatrixCounter];k++) {
     234        output << scientific << Time.Matrix[ Time.MatrixCounter ][j][k] << "\t";
     235      }
     236      output << endl;
     237    }
     238    output << endl;
     239  }
     240  output.close();
     241  if (!NoTime)
     242    for(int k=0;k<Time.ColumnCounter[Time.MatrixCounter];k++)
     243      Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k] = Time.Matrix[ Time.MatrixCounter ][Time.RowCounter[Time.MatrixCounter]-1][k];
     244
     245  // +++++++++++++++ ANALYZING ++++++++++++++++++++++++++++++
     246
     247  cout << "Analyzing ..." << endl;
     248
     249  // ======================================= Creating the data files ==============================================================
     250
     251  // +++++++++++++++++++++++++++++++++++++++ Plotting Simtime vs Bond Order
     252  // +++++++++++++++++++++++++++++++++++++++ Plotting Delta Simtime vs Bond Order
     253  if (!NoTime) {
     254    if (!OpenOutputFile(output, argv[3], "SimTime-Order.dat" )) return false;
     255    if (!OpenOutputFile(output2, argv[3], "DeltaSimTime-Order.dat" )) return false;
     256    for(int j=Time.RowCounter[Time.MatrixCounter];j--;)
     257      for(int k=Time.ColumnCounter[Time.MatrixCounter];k--;) {
     258        Time.Matrix[ Time.MatrixCounter ][j][k] = 0.;
     259      }
     260    counter = 0;
     261    output << "#Order\tFrag.No.\t" << Time.Header[Time.MatrixCounter] << endl;
     262    output2 << "#Order\tFrag.No.\t" << Time.Header[Time.MatrixCounter] << endl;
     263    for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     264      for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;)
     265        for(int j=Time.RowCounter[Time.MatrixCounter];j--;)
     266          for(int k=Time.ColumnCounter[Time.MatrixCounter];k--;) {
     267            Time.Matrix[ Time.MatrixCounter ][j][k] += Time.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
     268          }
     269      counter += KeySet.FragmentsPerOrder[BondOrder];
     270      output << BondOrder+1 << "\t" << counter;
     271      output2 << BondOrder+1 << "\t" << counter;
     272      for(int k=0;k<Time.ColumnCounter[Time.MatrixCounter];k++) {
     273        output << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k];
     274        if (fabs(Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k]) > MYEPSILON)
     275          output2 << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k] / Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k];
     276        else
     277          output2 << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k];
     278      }
     279      output << endl;
     280      output2 << endl;
     281    }
     282    output.close();
     283    output2.close();
     284  }
     285
     286  if (!NoHessian) {
     287    // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in hessian to full QM
     288    if (!CreateDataDeltaHessianOrderPerAtom(Hessian, HessianFragments, KeySet, argv[3], "DeltaHessian_xx-Order", "Plot of error between approximated hessian and full hessian versus the Bond Order", datum)) return 1;
     289
     290    if (!CreateDataDeltaFrobeniusOrderPerAtom(Hessian, HessianFragments, KeySet, argv[3], "DeltaFrobeniusHessian_xx-Order", "Plot of error between approximated hessian and full hessian in the frobenius norm versus the Bond Order", datum)) return 1;
     291
     292    // ++++++++++++++++++++++++++++++++++++++Plotting Hessian vs. Order
     293    if (!CreateDataHessianOrderPerAtom(HessianFragments, KeySet, argv[3], "Hessian_xx-Order", "Plot of approximated hessian versus the Bond Order", datum)) return 1;
     294    if (!AppendOutputFile(output, argv[3], "Hessian_xx-Order.dat" )) return false;
     295    output << endl << "# Full" << endl;
     296    for(int j=0;j<Hessian.RowCounter[Hessian.MatrixCounter];j++) {
     297      output << j << "\t";
     298      for(int k=0;k<Hessian.ColumnCounter[Force.MatrixCounter];k++)
     299        output << scientific <<  Hessian.Matrix[ Hessian.MatrixCounter ][j][k] << "\t";
     300      output << endl;
     301    }
     302    output.close();
     303  }
     304
     305  // +++++++++++++++++++++++++++++++++++++++ Plotting shieldings
     306  if (periode != NULL) { // also look for PAS values
     307    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;
     308    if (!CreateDataForcesOrderPerAtom(ShieldingPASFragments, KeySet, argv[3], "ShieldingsPAS-Order", "Plot of approximated shieldings versus the Bond Order", datum)) return 1;
     309    if (!AppendOutputFile(output, argv[3], "ShieldingsPAS-Order.dat" )) return false;
     310    output << endl << "# Full" << endl;
     311    for(int j=0;j<ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter];j++) {
     312      output << j << "\t";
     313      for(int k=0;k<ShieldingPAS.ColumnCounter[ShieldingPAS.MatrixCounter];k++)
     314        output << scientific <<  ShieldingPAS.Matrix[ ShieldingPAS.MatrixCounter ][j][k] << "\t"; //*(((k>1) && (k<6))? 1.e6 : 1.) << "\t";
     315      output << endl;
     316    }
     317    output.close();
     318    if (!CreateDataDeltaForcesOrderPerAtom(ChiPAS, ChiPASFragments, KeySet, argv[3], "DeltaChisPAS-Order", "Plot of error between approximated Chis and full Chis versus the Bond Order", datum)) return 1;
     319    if (!CreateDataForcesOrderPerAtom(ChiPASFragments, KeySet, argv[3], "ChisPAS-Order", "Plot of approximated Chis versus the Bond Order", datum)) return 1;
     320    if (!AppendOutputFile(output, argv[3], "ChisPAS-Order.dat" )) return false;
     321    output << endl << "# Full" << endl;
     322    for(int j=0;j<ChiPAS.RowCounter[ChiPAS.MatrixCounter];j++) {
     323      output << j << "\t";
     324      for(int k=0;k<ChiPAS.ColumnCounter[ChiPAS.MatrixCounter];k++)
     325        output << scientific <<  ChiPAS.Matrix[ ChiPAS.MatrixCounter ][j][k] << "\t"; //*(((k>1) && (k<6))? 1.e6 : 1.) << "\t";
     326      output << endl;
     327    }
     328    output.close();
     329  }
     330
     331
     332  // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in energy to full QM
     333  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;
     334
     335  // +++++++++++++++++++++++++++++++++++Plotting Energies vs. Order
     336  if (!CreateDataEnergyOrder(EnergyFragments, KeySet, argv[3], "Energies-Order", "Plot of approximated energies versus the Bond Order", datum)) return 1;
     337
     338  // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in forces to full QM
     339  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;
     340
     341  // min force
     342  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;
     343
     344  // mean force
     345  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;
     346
     347  // max force
     348  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;
     349
     350  // ++++++++++++++++++++++++++++++++++++++Plotting Forces vs. Order
     351  if (!CreateDataForcesOrderPerAtom(ForceFragments, KeySet, argv[3], "Forces-Order", "Plot of approximated forces versus the Bond Order", datum)) return 1;
     352  if (!AppendOutputFile(output, argv[3], "Forces-Order.dat" )) return false;
     353  output << endl << "# Full" << endl;
     354  for(int j=0;j<Force.RowCounter[Force.MatrixCounter];j++) {
     355    output << j << "\t";
     356    for(int k=0;k<Force.ColumnCounter[Force.MatrixCounter];k++)
     357      output << scientific <<  Force.Matrix[ Force.MatrixCounter ][j][k] << "\t";
     358    output << endl;
     359  }
     360  output.close();
     361  // min force
     362  if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MinForces-Order", "Plot of min approximated forces versus the Bond Order", datum, CreateMinimumForce)) return 1;
     363
     364  // mean force
     365  if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MeanForces-Order", "Plot of mean approximated forces versus the Bond Order", datum, CreateMeanForce)) return 1;
     366
     367  // max force
     368  if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MaxForces-Order", "Plot of max approximated forces versus the Bond Order", datum, CreateMaximumForce)) return 1;
     369
     370  // ++++++++++++++++++++++++++++++++++++++Plotting vector sum (should be 0) vs. bond order
     371  if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "VectorSum-Order", "Plot of vector sum of the approximated forces versus the Bond Order", datum, CreateVectorSumForce)) return 1;
     372
     373  // +++++++++++++++++++++++++++++++Plotting energyfragments vs. order
     374  if (!CreateDataFragment(EnergyFragments, KeySet, argv[3], "Energies-Fragment", "Plot of fragment energy versus the Fragment No", datum, CreateEnergy)) return 1;
     375  if (!CreateDataFragment(EnergyFragments, KeySet, argv[3], "Energies-FragmentOrder", "Plot of fragment energy of each Fragment No vs. Bond Order", datum, CreateEnergy)) return 1;
     376  if (!CreateDataFragmentOrder(EnergyFragments, KeySet, argv[3], "MaxEnergies-FragmentOrder", "Plot of maximum of fragment energy vs. Bond Order", datum, CreateMaxFragmentOrder)) return 1;
     377  if (!CreateDataFragmentOrder(EnergyFragments, KeySet, argv[3], "MinEnergies-FragmentOrder", "Plot of minimum of fragment energy vs. Bond Order", datum, CreateMinFragmentOrder)) return 1;
     378
     379  // +++++++++++++++++++++++++++++++Ploting min/mean/max forces for each fragment
     380  // min force
     381  if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MinForces-Fragment", "Plot of min approximated forces versus the Fragment No", datum, CreateMinimumForce)) return 1;
     382
     383  // mean force
     384  if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MeanForces-Fragment", "Plot of mean approximated forces versus the Fragment No", datum, CreateMeanForce)) return 1;
     385
     386  // max force
     387  if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MaxForces-Fragment", "Plot of max approximated forces versus the Fragment No", datum, CreateMaximumForce)) return 1;
     388
     389  // +++++++++++++++++++++++++++++++Ploting min/mean/max forces for each fragment per order
     390  // min force
     391  if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MinForces-FragmentOrder", "Plot of min approximated forces of each Fragment No vs. Bond Order", datum, CreateMinimumForce)) return 1;
     392
     393  // mean force
     394  if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MeanForces-FragmentOrder", "Plot of mean approximated forces of each Fragment No vs. Bond Order", datum, CreateMeanForce)) return 1;
     395
     396  // max force
     397  if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MaxForces-FragmentOrder", "Plot of max approximated forces of each Fragment No vs. Bond Order", datum, CreateMaximumForce)) return 1;
     398
     399  // ======================================= Creating the plot files ==============================================================
     400
     401  Orderxrange << "[1:" << KeySet.Order << "]";
     402  Fragmentxrange << "[0:" << KeySet.FragmentCounter+1 << "]";
     403  yrange.str("[1e-8:1e+1]");
     404 
     405  if (!NoTime) {
     406    // +++++++++++++++++++++++++++++++++++++++ Plotting Simtime vs Bond Order
     407    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;
     408  }
     409 
     410  // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in energy to full QM
     411  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;
     412
     413  // +++++++++++++++++++++++++++++++++++Plotting Energies vs. Order
     414  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;
     415
     416  // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in forces to full QM
     417  yrange.str("[1e-8:1e+0]");
     418  // min force
     419  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;
     420
     421  // mean force
     422  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;
     423
     424  // max force
     425  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;
     426
     427  // min/mean/max comparison for total force
     428  if(!OpenOutputFile(output, argv[3], "DeltaMinMeanMaxTotalForce-Order.pyx")) return 1;
     429  CreatePlotHeader(output, "DeltaMinMeanMaxTotalForce-Order", 1, "bottom left", "y", NULL,  1, 1, "bond order k", "absolute error in total forces [Ht/a.u.]");
     430  output << "plot " << Orderxrange.str().c_str() << " [1e-8:1e+0] \\" << endl;
     431  output << "'DeltaMinForces-Order.dat' title 'minimum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints, \\" << endl;
     432  output << "'DeltaMeanForces-Order.dat' title 'mean' using 1:(abs($" << 8 << ")) with linespoints, \\" << endl;
     433  output << "'DeltaMaxForces-Order.dat' title 'maximum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints" << endl;
     434  output.close();
     435
     436  // ++++++++++++++++++++++++++++++++++++++Plotting Forces vs. Order
     437  // min force
     438  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;
     439
     440  // mean force
     441  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;
     442
     443  // max force
     444  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;
     445
     446  // min/mean/max comparison for total force
     447  if(!OpenOutputFile(output, argv[3],"MinMeanMaxTotalForce-Order.pyx")) return 1;
     448  CreatePlotHeader(output, "MinMeanMaxTotalForce-Order", 1, "bottom left", "y", NULL, 1, 1, "bond order k", "absolute total force [Ht/a.u.]");
     449  output << "plot "<< Orderxrange.str().c_str() << " [1e-8:1e+0] \\" << endl;
     450  output << "'MinForces-Order.dat' title 'minimum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints, \\" << endl;
     451  output << "'MeanForces-Order.dat' title 'mean' using 1:(abs($" << 8 << ")) with linespoints, \\" << endl;
     452  output << "'MaxForces-Order.dat' title 'maximum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints" << endl;
     453  output.close();
     454
     455  // ++++++++++++++++++++++++++++++++++++++Plotting vector sum vs. Order
     456
     457  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;
     458
     459  // +++++++++++++++++++++++++++++++Plotting energyfragments vs. order
     460  yrange.str("");
     461  yrange << "[" << EnergyFragments.FindMinValue() << ":" << EnergyFragments.FindMaxValue() << "]";
     462  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;
     463  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;
     464  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;
     465  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;
     466
     467  // +++++++++++++++++++++++++++++++=Ploting min/mean/max forces for each fragment
     468  yrange.str("");
     469  yrange << "[" << ForceFragments.FindMinValue() << ":" << ForceFragments.FindMaxValue()<< "]";
     470  // min
     471  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;
     472
     473  // mean
     474  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;
     475
     476  // max
     477  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;
     478
     479  // +++++++++++++++++++++++++++++++=Ploting min/mean/max forces for each fragment per bond order
     480  // min
     481  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;
     482
     483  // mean
     484  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;
     485
     486  // max
     487  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;
     488
     489  // +++++++++++++++++++++++++++++++=Ploting approximated and true shielding for each atom
     490  if (periode != NULL) { // also look for PAS values
     491    if(!OpenOutputFile(output, argv[3], "ShieldingsPAS-Order.pyx")) return 1;
     492    if(!OpenOutputFile(output2, argv[3], "DeltaShieldingsPAS-Order.pyx")) return 1;
     493    CreatePlotHeader(output, "ShieldingsPAS-Order", 1, "top right", NULL, NULL,  1, 5, "nuclei index", "iso chemical shielding value [ppm]");
     494    CreatePlotHeader(output2, "DeltaShieldingsPAS-Order", 1, "top right", NULL, NULL,  1, 5, "nuclei index", "iso chemical shielding value [ppm]");
     495    double step=0.8/KeySet.Order;
     496    output << "set boxwidth " << step << endl;
     497    output << "plot [0:" << ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter]+10 << "]\\" << endl;
     498    output2 << "plot [0:" << ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter]+10 << "]\\" << endl;
     499    for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     500      output << "'ShieldingsPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1+" << step*(double)BondOrder << "):7 with boxes, \\" << endl;
     501      output2 << "'DeltaShieldingsPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1):7 with linespoints";
     502      if (BondOrder-1 != KeySet.Order)
     503        output2 << ", \\" << endl;
     504    }
     505    output << "'ShieldingsPAS-Order.dat' index " << KeySet.Order << " title 'Full' using ($1+" << step*(double)KeySet.Order << "):7 with boxes" << endl;
     506    output2.close(); 
     507
     508    if(!OpenOutputFile(output, argv[3], "ChisPAS-Order.pyx")) return 1;
     509    if(!OpenOutputFile(output2, argv[3], "DeltaChisPAS-Order.pyx")) return 1;
     510    CreatePlotHeader(output, "ChisPAS-Order", 1, "top right", NULL, NULL,  1, 5, "nuclei index", "iso chemical Chi value [ppm]");
     511    CreatePlotHeader(output2, "DeltaChisPAS-Order", 1, "top right", NULL, NULL,  1, 5, "nuclei index", "iso chemical Chi value [ppm]");
     512    output << "set boxwidth " << step << endl;
     513    output << "plot [0:" << ChiPAS.RowCounter[ChiPAS.MatrixCounter]+10 << "]\\" << endl;
     514    output2 << "plot [0:" << ChiPAS.RowCounter[ChiPAS.MatrixCounter]+10 << "]\\" << endl;
     515    for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     516      output << "'ChisPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1+" << step*(double)BondOrder << "):7 with boxes, \\" << endl;
     517      output2 << "'DeltaChisPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1):7 with linespoints";
     518      if (BondOrder-1 != KeySet.Order)
     519        output2 << ", \\" << endl;
     520    }
     521    output << "'ChisPAS-Order.dat' index " << KeySet.Order << " title 'Full' using ($1+" << step*(double)KeySet.Order << "):7 with boxes" << endl;
     522    output.close(); 
     523    output2.close(); 
     524
     525    if(!OpenOutputFile(output, argv[3], "ChisPAS-Order.pyx")) return 1;
     526    if(!OpenOutputFile(output2, argv[3], "DeltaChisPAS-Order.pyx")) return 1;
     527    CreatePlotHeader(output, "ChisPAS-Order", 1, "top right", NULL, NULL,  1, 5, "nuclei index", "iso chemical Chi value [ppm]");
     528    CreatePlotHeader(output2, "DeltaChisPAS-Order", 1, "top right", NULL, NULL,  1, 5, "nuclei index", "iso chemical Chi value [ppm]");
     529    output << "set boxwidth " << step << endl;
     530    output << "plot [0:" << ChiPAS.RowCounter[ChiPAS.MatrixCounter]+10 << "]\\" << endl;
     531    output2 << "plot [0:" << ChiPAS.RowCounter[ChiPAS.MatrixCounter]+10 << "]\\" << endl;
     532    for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     533      output << "'ChisPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1+" << step*(double)BondOrder << "):7 with boxes, \\" << endl;
     534      output2 << "'DeltaChisPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1):7 with linespoints";
     535      if (BondOrder-1 != KeySet.Order)
     536        output2 << ", \\" << endl;
     537    }
     538    output << "'ChisPAS-Order.dat' index " << KeySet.Order << " title 'Full' using ($1+" << step*(double)KeySet.Order << "):7 with boxes" << endl;
     539    output.close(); 
     540    output2.close(); 
     541  }
     542
     543  // create Makefile
     544  if(!OpenOutputFile(output, argv[3], "Makefile")) return 1;
     545  output << "PYX = $(shell ls *.pyx)" << endl << endl;
     546  output << "EPS = $(PYX:.pyx=.eps)" << endl << endl;
     547  output << "%.eps: %.pyx" << endl;
     548  output << "\t~/build/pyxplot/pyxplot $<" << endl << endl;
     549  output << "all: $(EPS)" << endl << endl;
     550  output << ".PHONY: clean" << endl;
     551  output << "clean:" << endl;
     552  output << "\trm -rf $(EPS)" << endl;
     553  output.close();
     554
     555  // ++++++++++++++++ exit ++++++++++++++++++++++++++++++++++
     556  delete(periode);
     557  Free((void **)&dir, "main: *dir");
     558  cout << "done." << endl;
     559  return 0;
    427560};
    428561
  • src/atom.cpp

    r375b458 r51c910  
    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
    91 ostream & operator << (ostream &ost, atom &a)
     91ostream & operator << (ostream &ost, const 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

    r375b458 r51c910  
    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
    84 ostream & operator << (ostream &ost, bond &b)
     84ostream & operator << (ostream &ost, const 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  cerr << "Bond " << *this << " does not contain atom " << *Atom << "!" << endl;
     101  return NULL;
    101102};
    102103
     
    107108bond * bond::GetFirstBond()
    108109{
    109         return GetFirst(this);
     110  return GetFirst(this);
    110111};
    111112
     
    116117bond * bond::GetLastBond()
    117118{
    118         return GetLast(this);
     119  return GetLast(this);
    119120};
    120121
     
    124125enum Shading bond::IsUsed()
    125126{
    126         return Used;
     127  return Used;
    127128};
    128129
     
    133134bool bond::Contains(const atom *ptr)
    134135{
    135         return ((leftatom == ptr) || (rightatom == ptr));
     136  return ((leftatom == ptr) || (rightatom == ptr));
    136137};
    137138
     
    142143bool bond::Contains(const int number)
    143144{
    144         return ((leftatom->nr == number) || (rightatom->nr == number));
     145  return ((leftatom->nr == number) || (rightatom->nr == number));
    145146};
    146147
     
    149150 */
    150151bool 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         }
     152  if (Used == black) {
     153    cerr << "ERROR: Bond " << this << " was already marked black!." << endl;
     154    return false;
     155  } else {
     156    Used = color;
     157    return true;
     158  }
    158159};
    159160
     
    162163 */
    163164void bond::ResetUsed() {
    164         Used = white;
     165  Used = white;
    165166};
  • src/boundary.cpp

    r375b458 r51c910  
    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;
     36  lines.clear();
    3637}
    3738;
     
    3940void BoundaryPointSet::AddLine(class BoundaryLineSet *line)
    4041{
    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++;
     42  cout << Verbose(6) << "Adding " << *this << " to line " << *line << "."
     43      << endl;
     44  if (line->endpoints[0] == this)
     45    {
     46      lines.insert(LinePair(line->endpoints[1]->Nr, line));
     47    }
     48  else
     49    {
     50      lines.insert(LinePair(line->endpoints[0]->Nr, line));
     51    }
     52  LinesCount++;
    5253}
    5354;
     
    5657operator <<(ostream &ost, BoundaryPointSet &a)
    5758{
    58         ost << "[" << a.Nr << "|" << a.node->Name << "]";
    59         return ost;
     59  ost << "[" << a.Nr << "|" << a.node->Name << "]";
     60  return ost;
    6061}
    6162;
     
    6566BoundaryLineSet::BoundaryLineSet()
    6667{
    67         for (int i = 0; i < 2; i++)
    68                 endpoints[i] = NULL;
    69         TrianglesCount = 0;
    70         Nr = -1;
     68  for (int i = 0; i < 2; i++)
     69    endpoints[i] = NULL;
     70  TrianglesCount = 0;
     71  Nr = -1;
    7172}
    7273;
     
    7475BoundaryLineSet::BoundaryLineSet(class BoundaryPointSet *Point[2], int number)
    7576{
    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;
     77  // set number
     78  Nr = number;
     79  // set endpoints in ascending order
     80  SetEndpointsOrdered(endpoints, Point[0], Point[1]);
     81  // add this line to the hash maps of both endpoints
     82  Point[0]->AddLine(this); //Taken out, to check whether we can avoid unwanted double adding.
     83  Point[1]->AddLine(this); //
     84  // clear triangles list
     85  TrianglesCount = 0;
     86  cout << Verbose(5) << "New Line with endpoints " << *this << "." << endl;
    8687}
    8788;
     
    8990BoundaryLineSet::~BoundaryLineSet()
    9091{
    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;
     92  for (int i = 0; i < 2; i++) {
     93    cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl;
     94    endpoints[i]->lines.erase(Nr);
     95    LineMap::iterator tester = endpoints[i]->lines.begin();
     96    tester++;
     97    if (tester == endpoints[i]->lines.end()) {
     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  }
     1022  for (LineMap::iterator runner = LinesOnBoundary.begin(); runner != LinesOnBoundary.end(); runner++) {
     1023    if (runner->second != NULL) {
     1024      delete (runner->second);
     1025      runner->second = NULL;
     1026    } else
     1027      cerr << "ERROR: The line " << runner->first << " has already been free'd." << endl;
     1028  }
     1029  for (PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) {
     1030    if (runner->second != NULL) {
     1031      delete (runner->second);
     1032      runner->second = NULL;
     1033    } else
     1034      cerr << "ERROR: The point " << runner->first << " has already been free'd." << endl;
     1035  }
    10221036}
    10231037;
     
    10311045Tesselation::GuessStartingTriangle(ofstream *out)
    10321046{
    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                 }
     1047  // 4b. create a starting triangle
     1048  // 4b1. create all distances
     1049  DistanceMultiMap DistanceMMap;
     1050  double distance, tmp;
     1051  Vector PlaneVector, TrialVector;
     1052  PointMap::iterator A, B, C; // three nodes of the first triangle
     1053  A = PointsOnBoundary.begin(); // the first may be chosen arbitrarily
     1054
     1055  // with A chosen, take each pair B,C and sort
     1056  if (A != PointsOnBoundary.end())
     1057    {
     1058      B = A;
     1059      B++;
     1060      for (; B != PointsOnBoundary.end(); B++)
     1061        {
     1062          C = B;
     1063          C++;
     1064          for (; C != PointsOnBoundary.end(); C++)
     1065            {
     1066              tmp = A->second->node->x.DistanceSquared(&B->second->node->x);
     1067              distance = tmp * tmp;
     1068              tmp = A->second->node->x.DistanceSquared(&C->second->node->x);
     1069              distance += tmp * tmp;
     1070              tmp = B->second->node->x.DistanceSquared(&C->second->node->x);
     1071              distance += tmp * tmp;
     1072              DistanceMMap.insert(DistanceMultiMapPair(distance, pair<
     1073                  PointMap::iterator, PointMap::iterator> (B, C)));
     1074            }
     1075        }
     1076    }
     1077  //    // listing distances
     1078  //    *out << Verbose(1) << "Listing DistanceMMap:";
     1079  //    for(DistanceMultiMap::iterator runner = DistanceMMap.begin(); runner != DistanceMMap.end(); runner++) {
     1080  //      *out << " " << runner->first << "(" << *runner->second.first->second << ", " << *runner->second.second->second << ")";
     1081  //    }
     1082  //    *out << endl;
     1083  // 4b2. pick three baselines forming a triangle
     1084  // 1. we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate
     1085  DistanceMultiMap::iterator baseline = DistanceMMap.begin();
     1086  for (; baseline != DistanceMMap.end(); baseline++)
     1087    {
     1088      // we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate
     1089      // 2. next, we have to check whether all points reside on only one side of the triangle
     1090      // 3. construct plane vector
     1091      PlaneVector.MakeNormalVector(&A->second->node->x,
     1092          &baseline->second.first->second->node->x,
     1093          &baseline->second.second->second->node->x);
     1094      *out << Verbose(2) << "Plane vector of candidate triangle is ";
     1095      PlaneVector.Output(out);
     1096      *out << endl;
     1097      // 4. loop over all points
     1098      double sign = 0.;
     1099      PointMap::iterator checker = PointsOnBoundary.begin();
     1100      for (; checker != PointsOnBoundary.end(); checker++)
     1101        {
     1102          // (neglecting A,B,C)
     1103          if ((checker == A) || (checker == baseline->second.first) || (checker
     1104              == baseline->second.second))
     1105            continue;
     1106          // 4a. project onto plane vector
     1107          TrialVector.CopyVector(&checker->second->node->x);
     1108          TrialVector.SubtractVector(&A->second->node->x);
     1109          distance = TrialVector.Projection(&PlaneVector);
     1110          if (fabs(distance) < 1e-4) // we need to have a small epsilon around 0 which is still ok
     1111            continue;
     1112          *out << Verbose(3) << "Projection of " << checker->second->node->Name
     1113              << " yields distance of " << distance << "." << endl;
     1114          tmp = distance / fabs(distance);
     1115          // 4b. Any have different sign to than before? (i.e. would lie outside convex hull with this starting triangle)
     1116          if ((sign != 0) && (tmp != sign))
     1117            {
     1118              // 4c. If so, break 4. loop and continue with next candidate in 1. loop
     1119              *out << Verbose(2) << "Current candidates: "
     1120                  << A->second->node->Name << ","
     1121                  << baseline->second.first->second->node->Name << ","
     1122                  << baseline->second.second->second->node->Name << " leave "
     1123                  << checker->second->node->Name << " outside the convex hull."
     1124                  << endl;
     1125              break;
     1126            }
     1127          else
     1128            { // note the sign for later
     1129              *out << Verbose(2) << "Current candidates: "
     1130                  << A->second->node->Name << ","
     1131                  << baseline->second.first->second->node->Name << ","
     1132                  << baseline->second.second->second->node->Name << " leave "
     1133                  << checker->second->node->Name << " inside the convex hull."
     1134                  << endl;
     1135              sign = tmp;
     1136            }
     1137          // 4d. Check whether the point is inside the triangle (check distance to each node
     1138          tmp = checker->second->node->x.DistanceSquared(&A->second->node->x);
     1139          int innerpoint = 0;
     1140          if ((tmp < A->second->node->x.DistanceSquared(
     1141              &baseline->second.first->second->node->x)) && (tmp
     1142              < A->second->node->x.DistanceSquared(
     1143                  &baseline->second.second->second->node->x)))
     1144            innerpoint++;
     1145          tmp = checker->second->node->x.DistanceSquared(
     1146              &baseline->second.first->second->node->x);
     1147          if ((tmp < baseline->second.first->second->node->x.DistanceSquared(
     1148              &A->second->node->x)) && (tmp
     1149              < baseline->second.first->second->node->x.DistanceSquared(
     1150                  &baseline->second.second->second->node->x)))
     1151            innerpoint++;
     1152          tmp = checker->second->node->x.DistanceSquared(
     1153              &baseline->second.second->second->node->x);
     1154          if ((tmp < baseline->second.second->second->node->x.DistanceSquared(
     1155              &baseline->second.first->second->node->x)) && (tmp
     1156              < baseline->second.second->second->node->x.DistanceSquared(
     1157                  &A->second->node->x)))
     1158            innerpoint++;
     1159          // 4e. If so, break 4. loop and continue with next candidate in 1. loop
     1160          if (innerpoint == 3)
     1161            break;
     1162        }
     1163      // 5. come this far, all on same side? Then break 1. loop and construct triangle
     1164      if (checker == PointsOnBoundary.end())
     1165        {
     1166          *out << "Looks like we have a candidate!" << endl;
     1167          break;
     1168        }
     1169    }
     1170  if (baseline != DistanceMMap.end())
     1171    {
     1172      BPS[0] = baseline->second.first->second;
     1173      BPS[1] = baseline->second.second->second;
     1174      BLS[0] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
     1175      BPS[0] = A->second;
     1176      BPS[1] = baseline->second.second->second;
     1177      BLS[1] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
     1178      BPS[0] = baseline->second.first->second;
     1179      BPS[1] = A->second;
     1180      BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
     1181
     1182      // 4b3. insert created triangle
     1183      BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     1184      TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
     1185      TrianglesOnBoundaryCount++;
     1186      for (int i = 0; i < NDIM; i++)
     1187        {
     1188          LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BTS->lines[i]));
     1189          LinesOnBoundaryCount++;
     1190        }
     1191
     1192      *out << Verbose(1) << "Starting triangle is " << *BTS << "." << endl;
     1193    }
     1194  else
     1195    {
     1196      *out << Verbose(1) << "No starting triangle found." << endl;
     1197      exit(255);
     1198    }
    11851199}
    11861200;
     
    11911205 * -# if the lines contains to only one triangle
    11921206 * -# 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)
     1207 *    -# if the triangle with the baseline and the current point has the smallest of angles (comparison between normal vectors
     1208 *    -# if the triangle is in forward direction of the baseline (at most 90 degrees angle between vector orthogonal to
     1209 *      baseline in triangle plane pointing out of the triangle and normal vector of new triangle)
     1210 *    -# then we have a new triangle, whose baselines we again add (or increase their TriangleCount)
    11971211 * \param *out output stream for debugging
    11981212 * \param *configuration for IsAngstroem
     
    12011215void
    12021216Tesselation::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);
     1217    molecule *mol)
     1218{
     1219  bool flag;
     1220  PointMap::iterator winner;
     1221  class BoundaryPointSet *peak = NULL;
     1222  double SmallestAngle, TempAngle;
     1223  Vector NormalVector, VirtualNormalVector, CenterVector, TempVector,
     1224      PropagationVector;
     1225  LineMap::iterator LineChecker[2];
     1226  do
     1227    {
     1228      flag = false;
     1229      for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline
     1230          != LinesOnBoundary.end(); baseline++)
     1231        if (baseline->second->TrianglesCount == 1)
     1232          {
     1233            *out << Verbose(2) << "Current baseline is between "
     1234                << *(baseline->second) << "." << endl;
     1235            // 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)
     1236            SmallestAngle = M_PI;
     1237            BTS = baseline->second->triangles.begin()->second; // there is only one triangle so far
     1238            // get peak point with respect to this base line's only triangle
     1239            for (int i = 0; i < 3; i++)
     1240              if ((BTS->endpoints[i] != baseline->second->endpoints[0])
     1241                  && (BTS->endpoints[i] != baseline->second->endpoints[1]))
     1242                peak = BTS->endpoints[i];
     1243            *out << Verbose(3) << " and has peak " << *peak << "." << endl;
     1244            // normal vector of triangle
     1245            BTS->GetNormalVector(NormalVector);
     1246            *out << Verbose(4) << "NormalVector of base triangle is ";
     1247            NormalVector.Output(out);
     1248            *out << endl;
     1249            // offset to center of triangle
     1250            CenterVector.Zero();
     1251            for (int i = 0; i < 3; i++)
     1252              CenterVector.AddVector(&BTS->endpoints[i]->node->x);
     1253            CenterVector.Scale(1. / 3.);
     1254            *out << Verbose(4) << "CenterVector of base triangle is ";
     1255            CenterVector.Output(out);
     1256            *out << endl;
     1257            // vector in propagation direction (out of triangle)
     1258            // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection)
     1259            TempVector.CopyVector(&baseline->second->endpoints[0]->node->x);
     1260            TempVector.SubtractVector(&baseline->second->endpoints[1]->node->x);
     1261            PropagationVector.MakeNormalVector(&TempVector, &NormalVector);
     1262            TempVector.CopyVector(&CenterVector);
     1263            TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center!
     1264            //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl;
     1265            if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline
     1266              PropagationVector.Scale(-1.);
     1267            *out << Verbose(4) << "PropagationVector of base triangle is ";
     1268            PropagationVector.Output(out);
     1269            *out << endl;
     1270            winner = PointsOnBoundary.end();
     1271            for (PointMap::iterator target = PointsOnBoundary.begin(); target
     1272                != PointsOnBoundary.end(); target++)
     1273              if ((target->second != baseline->second->endpoints[0])
     1274                  && (target->second != baseline->second->endpoints[1]))
     1275                { // don't take the same endpoints
     1276                  *out << Verbose(3) << "Target point is " << *(target->second)
     1277                      << ":";
     1278                  bool continueflag = true;
     1279
     1280                  VirtualNormalVector.CopyVector(
     1281                      &baseline->second->endpoints[0]->node->x);
     1282                  VirtualNormalVector.AddVector(
     1283                      &baseline->second->endpoints[0]->node->x);
     1284                  VirtualNormalVector.Scale(-1. / 2.); // points now to center of base line
     1285                  VirtualNormalVector.AddVector(&target->second->node->x); // points from center of base line to target
     1286                  TempAngle = VirtualNormalVector.Angle(&PropagationVector);
     1287                  continueflag = continueflag && (TempAngle < (M_PI/2.)); // no bends bigger than Pi/2 (90 degrees)
     1288                  if (!continueflag)
     1289                    {
     1290                      *out << Verbose(4)
     1291                          << "Angle between propagation direction and base line to "
     1292                          << *(target->second) << " is " << TempAngle
     1293                          << ", bad direction!" << endl;
     1294                      continue;
     1295                    }
     1296                  else
     1297                    *out << Verbose(4)
     1298                        << "Angle between propagation direction and base line to "
     1299                        << *(target->second) << " is " << TempAngle
     1300                        << ", good direction!" << endl;
     1301                  LineChecker[0] = baseline->second->endpoints[0]->lines.find(
     1302                      target->first);
     1303                  LineChecker[1] = baseline->second->endpoints[1]->lines.find(
     1304                      target->first);
     1305                  //            if (LineChecker[0] != baseline->second->endpoints[0]->lines.end())
     1306                  //              *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl;
     1307                  //            else
     1308                  //              *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has no line to " << *(target->second) << " as endpoint." << endl;
     1309                  //            if (LineChecker[1] != baseline->second->endpoints[1]->lines.end())
     1310                  //              *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl;
     1311                  //            else
     1312                  //              *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has no line to " << *(target->second) << " as endpoint." << endl;
     1313                  // check first endpoint (if any connecting line goes to target or at least not more than 1)
     1314                  continueflag = continueflag && (((LineChecker[0]
     1315                      == baseline->second->endpoints[0]->lines.end())
     1316                      || (LineChecker[0]->second->TrianglesCount == 1)));
     1317                  if (!continueflag)
     1318                    {
     1319                      *out << Verbose(4) << *(baseline->second->endpoints[0])
     1320                          << " has line " << *(LineChecker[0]->second)
     1321                          << " to " << *(target->second)
     1322                          << " as endpoint with "
     1323                          << LineChecker[0]->second->TrianglesCount
     1324                          << " triangles." << endl;
     1325                      continue;
     1326                    }
     1327                  // check second endpoint (if any connecting line goes to target or at least not more than 1)
     1328                  continueflag = continueflag && (((LineChecker[1]
     1329                      == baseline->second->endpoints[1]->lines.end())
     1330                      || (LineChecker[1]->second->TrianglesCount == 1)));
     1331                  if (!continueflag)
     1332                    {
     1333                      *out << Verbose(4) << *(baseline->second->endpoints[1])
     1334                          << " has line " << *(LineChecker[1]->second)
     1335                          << " to " << *(target->second)
     1336                          << " as endpoint with "
     1337                          << LineChecker[1]->second->TrianglesCount
     1338                          << " triangles." << endl;
     1339                      continue;
     1340                    }
     1341                  // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint)
     1342                  continueflag = continueflag && (!(((LineChecker[0]
     1343                      != baseline->second->endpoints[0]->lines.end())
     1344                      && (LineChecker[1]
     1345                          != baseline->second->endpoints[1]->lines.end())
     1346                      && (GetCommonEndpoint(LineChecker[0]->second,
     1347                          LineChecker[1]->second) == peak))));
     1348                  if (!continueflag)
     1349                    {
     1350                      *out << Verbose(4) << "Current target is peak!" << endl;
     1351                      continue;
     1352                    }
     1353                  // in case NOT both were found
     1354                  if (continueflag)
     1355                    { // create virtually this triangle, get its normal vector, calculate angle
     1356                      flag = true;
     1357                      VirtualNormalVector.MakeNormalVector(
     1358                          &baseline->second->endpoints[0]->node->x,
     1359                          &baseline->second->endpoints[1]->node->x,
     1360                          &target->second->node->x);
     1361                      // make it always point inward
     1362                      if (baseline->second->endpoints[0]->node->x.Projection(
     1363                          &VirtualNormalVector) > 0)
     1364                        VirtualNormalVector.Scale(-1.);
     1365                      // calculate angle
     1366                      TempAngle = NormalVector.Angle(&VirtualNormalVector);
     1367                      *out << Verbose(4) << "NormalVector is ";
     1368                      VirtualNormalVector.Output(out);
     1369                      *out << " and the angle is " << TempAngle << "." << endl;
     1370                      if (SmallestAngle > TempAngle)
     1371                        { // set to new possible winner
     1372                          SmallestAngle = TempAngle;
     1373                          winner = target;
     1374                        }
     1375                    }
     1376                }
     1377            // 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
     1378            if (winner != PointsOnBoundary.end())
     1379              {
     1380                *out << Verbose(2) << "Winning target point is "
     1381                    << *(winner->second) << " with angle " << SmallestAngle
     1382                    << "." << endl;
     1383                // create the lins of not yet present
     1384                BLS[0] = baseline->second;
     1385                // 5c. add lines to the line set if those were new (not yet part of a triangle), delete lines that belong to two triangles)
     1386                LineChecker[0] = baseline->second->endpoints[0]->lines.find(
     1387                    winner->first);
     1388                LineChecker[1] = baseline->second->endpoints[1]->lines.find(
     1389                    winner->first);
     1390                if (LineChecker[0]
     1391                    == baseline->second->endpoints[0]->lines.end())
     1392                  { // create
     1393                    BPS[0] = baseline->second->endpoints[0];
     1394                    BPS[1] = winner->second;
     1395                    BLS[1] = new class BoundaryLineSet(BPS,
     1396                        LinesOnBoundaryCount);
     1397                    LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount,
     1398                        BLS[1]));
     1399                    LinesOnBoundaryCount++;
     1400                  }
     1401                else
     1402                  BLS[1] = LineChecker[0]->second;
     1403                if (LineChecker[1]
     1404                    == baseline->second->endpoints[1]->lines.end())
     1405                  { // create
     1406                    BPS[0] = baseline->second->endpoints[1];
     1407                    BPS[1] = winner->second;
     1408                    BLS[2] = new class BoundaryLineSet(BPS,
     1409                        LinesOnBoundaryCount);
     1410                    LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount,
     1411                        BLS[2]));
     1412                    LinesOnBoundaryCount++;
     1413                  }
     1414                else
     1415                  BLS[2] = LineChecker[1]->second;
     1416                BTS = new class BoundaryTriangleSet(BLS,
     1417                    TrianglesOnBoundaryCount);
     1418                TrianglesOnBoundary.insert(TrianglePair(
     1419                    TrianglesOnBoundaryCount, BTS));
     1420                TrianglesOnBoundaryCount++;
     1421              }
     1422            else
     1423              {
     1424                *out << Verbose(1)
     1425                    << "I could not determine a winner for this baseline "
     1426                    << *(baseline->second) << "." << endl;
     1427              }
     1428
     1429            // 5d. If the set of lines is not yet empty, go to 5. and continue
     1430          }
     1431        else
     1432          *out << Verbose(2) << "Baseline candidate " << *(baseline->second)
     1433              << " has a triangle count of "
     1434              << baseline->second->TrianglesCount << "." << endl;
     1435    }
     1436  while (flag);
    14231437
    14241438}
     
    14311445Tesselation::AddPoint(atom *Walker)
    14321446{
    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++;
     1447  PointTestPair InsertUnique;
     1448  BPS[0] = new class BoundaryPointSet(Walker);
     1449  InsertUnique = PointsOnBoundary.insert(PointPair(Walker->nr, BPS[0]));
     1450  if (InsertUnique.second) // if new point was not present before, increase counter
     1451    PointsOnBoundaryCount++;
    14381452}
    14391453;
     
    14471461Tesselation::AddTrianglePoint(atom* Candidate, int n)
    14481462{
    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                 }
     1463  PointTestPair InsertUnique;
     1464  TPS[n] = new class BoundaryPointSet(Candidate);
     1465  InsertUnique = PointsOnBoundary.insert(PointPair(Candidate->nr, TPS[n]));
     1466  if (InsertUnique.second) // if new point was not present before, increase counter
     1467    {
     1468      PointsOnBoundaryCount++;
     1469    }
     1470  else
     1471    {
     1472      delete TPS[n];
     1473      cout << Verbose(2) << "Atom " << *((InsertUnique.first)->second->node)
     1474          << " gibt's schon in der PointMap." << endl;
     1475      TPS[n] = (InsertUnique.first)->second;
     1476    }
    14631477}
    14641478;
     
    14731487void
    14741488Tesselation::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                 }
     1489    class BoundaryPointSet *b, int n)
     1490{
     1491  LineMap::iterator LineWalker;
     1492  //cout << "Manually checking endpoints for line." << endl;
     1493  if ((a->lines.find(b->node->nr)) != a->lines.end()) // ->first == b->node->nr)
     1494  //If a line is there, how do I recognize that beyond a shadow of a doubt?
     1495    {
     1496      //cout << Verbose(2) << "Line exists already, retrieving it from LinesOnBoundarySet" << endl;
     1497
     1498      LineWalker = LinesOnBoundary.end();
     1499      LineWalker--;
     1500
     1501      while (LineWalker->second->endpoints[0]->node->nr != min(a->node->nr,
     1502          b->node->nr) or LineWalker->second->endpoints[1]->node->nr != max(
     1503          a->node->nr, b->node->nr))
     1504        {
     1505          //cout << Verbose(1) << "Looking for line which already exists"<< endl;
     1506          LineWalker--;
     1507        }
     1508      BPS[0] = LineWalker->second->endpoints[0];
     1509      BPS[1] = LineWalker->second->endpoints[1];
     1510      BLS[n] = LineWalker->second;
     1511
     1512    }
     1513  else
     1514    {
     1515      cout << Verbose(2)
     1516          << "Adding line which has not been used before between "
     1517          << *(a->node) << " and " << *(b->node) << "." << endl;
     1518      BPS[0] = a;
     1519      BPS[1] = b;
     1520      BLS[n] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
     1521
     1522      LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BLS[n]));
     1523      LinesOnBoundaryCount++;
     1524
     1525    }
    15121526}
    15131527;
     
    15201534{
    15211535
    1522         cout << Verbose(1) << "Adding triangle to its lines" << endl;
    1523         int i = 0;
    1524         TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
    1525         TrianglesOnBoundaryCount++;
    1526 
    1527         /*
    1528          * this is apparently done when constructing triangle
    1529 
    1530          for (i=0; i<3; i++)
    1531          {
    1532          BLS[i]->AddTriangle(BTS);
    1533          }
    1534          */
     1536  cout << Verbose(1) << "Adding triangle to its lines" << endl;
     1537  TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
     1538  TrianglesOnBoundaryCount++;
     1539
     1540  /*
     1541   * this is apparently done when constructing triangle
     1542
     1543   for (int i=0; i<3; i++)
     1544   {
     1545   BLS[i]->AddTriangle(BTS);
     1546   }
     1547   */
    15351548}
    15361549;
     
    15381551
    15391552double det_get(gsl_matrix *A, int inPlace) {
    1540         /*
    1541         inPlace = 1 => A is replaced with the LU decomposed copy.
    1542         inPlace = 0 => A is retained, and a copy is used for LU.
    1543         */
    1544 
    1545         double det;
    1546         int signum;
    1547         gsl_permutation *p = gsl_permutation_alloc(A->size1);
    1548         gsl_matrix *tmpA;
    1549 
    1550         if (inPlace)
    1551         tmpA = A;
    1552         else {
    1553         gsl_matrix *tmpA = gsl_matrix_alloc(A->size1, A->size2);
    1554         gsl_matrix_memcpy(tmpA , A);
    1555         }
    1556 
    1557 
    1558         gsl_linalg_LU_decomp(tmpA , p , &signum);
    1559         det = gsl_linalg_LU_det(tmpA , signum);
    1560         gsl_permutation_free(p);
    1561         if (! inPlace)
    1562         gsl_matrix_free(tmpA);
    1563 
    1564         return det;
     1553  /*
     1554  inPlace = 1 => A is replaced with the LU decomposed copy.
     1555  inPlace = 0 => A is retained, and a copy is used for LU.
     1556  */
     1557
     1558  double det;
     1559  int signum;
     1560  gsl_permutation *p = gsl_permutation_alloc(A->size1);
     1561  gsl_matrix *tmpA;
     1562
     1563  if (inPlace)
     1564  tmpA = A;
     1565  else {
     1566  gsl_matrix *tmpA = gsl_matrix_alloc(A->size1, A->size2);
     1567  gsl_matrix_memcpy(tmpA , A);
     1568  }
     1569
     1570
     1571  gsl_linalg_LU_decomp(tmpA , p , &signum);
     1572  det = gsl_linalg_LU_det(tmpA , signum);
     1573  gsl_permutation_free(p);
     1574  if (! inPlace)
     1575  gsl_matrix_free(tmpA);
     1576
     1577  return det;
    15651578};
    15661579
    15671580void get_sphere(Vector *center, Vector &a, Vector &b, Vector &c, double RADIUS)
    15681581{
    1569         gsl_matrix *A = gsl_matrix_calloc(3,3);
    1570         double m11, m12, m13, m14;
    1571 
    1572         for(int i=0;i<3;i++) {
    1573                 gsl_matrix_set(A, i, 0, a.x[i]);
    1574                 gsl_matrix_set(A, i, 1, b.x[i]);
    1575                 gsl_matrix_set(A, i, 2, c.x[i]);
    1576         }
    1577         m11 = det_get(A, 1);
    1578 
    1579         for(int i=0;i<3;i++) {
    1580                 gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
    1581                 gsl_matrix_set(A, i, 1, b.x[i]);
    1582                 gsl_matrix_set(A, i, 2, c.x[i]);
    1583         }
    1584         m12 = det_get(A, 1);
    1585 
    1586         for(int i=0;i<3;i++) {
    1587                 gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
    1588                 gsl_matrix_set(A, i, 1, a.x[i]);
    1589                 gsl_matrix_set(A, i, 2, c.x[i]);
    1590         }
    1591         m13 = det_get(A, 1);
    1592 
    1593         for(int i=0;i<3;i++) {
    1594                 gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
    1595                 gsl_matrix_set(A, i, 1, a.x[i]);
    1596                 gsl_matrix_set(A, i, 2, b.x[i]);
    1597         }
    1598         m14 = det_get(A, 1);
    1599 
    1600         if (fabs(m11) < MYEPSILON)
    1601                 cerr << "ERROR: three points are colinear." << endl;
    1602 
    1603         center->x[0] =  0.5 * m12/ m11;
    1604         center->x[1] = -0.5 * m13/ m11;
    1605         center->x[2] =  0.5 * m14/ m11;
    1606 
    1607         if (fabs(a.Distance(center) - RADIUS) > MYEPSILON)
    1608                 cerr << "ERROR: The given center is further way by " << fabs(a.Distance(center) - RADIUS) << " from a than RADIUS." << endl;
    1609 
    1610         gsl_matrix_free(A);
     1582  gsl_matrix *A = gsl_matrix_calloc(3,3);
     1583  double m11, m12, m13, m14;
     1584
     1585  for(int i=0;i<3;i++) {
     1586    gsl_matrix_set(A, i, 0, a.x[i]);
     1587    gsl_matrix_set(A, i, 1, b.x[i]);
     1588    gsl_matrix_set(A, i, 2, c.x[i]);
     1589  }
     1590  m11 = 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, b.x[i]);
     1595    gsl_matrix_set(A, i, 2, c.x[i]);
     1596  }
     1597  m12 = det_get(A, 1);
     1598
     1599  for(int i=0;i<3;i++) {
     1600    gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
     1601    gsl_matrix_set(A, i, 1, a.x[i]);
     1602    gsl_matrix_set(A, i, 2, c.x[i]);
     1603  }
     1604  m13 = det_get(A, 1);
     1605
     1606  for(int i=0;i<3;i++) {
     1607    gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
     1608    gsl_matrix_set(A, i, 1, a.x[i]);
     1609    gsl_matrix_set(A, i, 2, b.x[i]);
     1610  }
     1611  m14 = det_get(A, 1);
     1612
     1613  if (fabs(m11) < MYEPSILON)
     1614    cerr << "ERROR: three points are colinear." << endl;
     1615
     1616  center->x[0] =  0.5 * m12/ m11;
     1617  center->x[1] = -0.5 * m13/ m11;
     1618  center->x[2] =  0.5 * m14/ m11;
     1619
     1620  if (fabs(a.Distance(center) - RADIUS) > MYEPSILON)
     1621    cerr << "ERROR: The given center is further way by " << fabs(a.Distance(center) - RADIUS) << " from a than RADIUS." << endl;
     1622
     1623  gsl_matrix_free(A);
    16111624};
    16121625
     
    16301643 */
    16311644void Get_center_of_sphere(Vector* Center, Vector a, Vector b, Vector c, Vector *NewUmkreismittelpunkt, Vector* Direction, Vector* AlternativeDirection,
    1632                 double HalfplaneIndicator, double AlternativeIndicator, double alpha, double beta, double gamma, double RADIUS, double Umkreisradius)
    1633 {
    1634         Vector TempNormal, helper;
    1635         double Restradius;
    1636         Vector OtherCenter;
    1637         cout << Verbose(3) << "Begin of Get_center_of_sphere.\n";
    1638         Center->Zero();
    1639         helper.CopyVector(&a);
    1640         helper.Scale(sin(2.*alpha));
    1641         Center->AddVector(&helper);
    1642         helper.CopyVector(&b);
    1643         helper.Scale(sin(2.*beta));
    1644         Center->AddVector(&helper);
    1645         helper.CopyVector(&c);
    1646         helper.Scale(sin(2.*gamma));
    1647         Center->AddVector(&helper);
    1648         //*Center = a * sin(2.*alpha) + b * sin(2.*beta) + c * sin(2.*gamma) ;
    1649         Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));
    1650         NewUmkreismittelpunkt->CopyVector(Center);
    1651         cout << Verbose(4) << "Center of new circumference is " << *NewUmkreismittelpunkt << ".\n";
    1652         // Here we calculated center of circumscribing circle, using barycentric coordinates
    1653         cout << Verbose(4) << "Center of circumference is " << *Center << " in direction " << *Direction << ".\n";
    1654 
    1655         TempNormal.CopyVector(&a);
    1656         TempNormal.SubtractVector(&b);
    1657         helper.CopyVector(&a);
    1658         helper.SubtractVector(&c);
    1659         TempNormal.VectorProduct(&helper);
    1660         if (fabs(HalfplaneIndicator) < MYEPSILON)
    1661                 {
    1662                         if ((TempNormal.ScalarProduct(AlternativeDirection) <0 and AlternativeIndicator >0) or (TempNormal.ScalarProduct(AlternativeDirection) >0 and AlternativeIndicator <0))
    1663                                 {
    1664                                         TempNormal.Scale(-1);
    1665                                 }
    1666                 }
    1667         else
    1668                 {
    1669                         if (TempNormal.ScalarProduct(Direction)<0 && HalfplaneIndicator >0 || TempNormal.ScalarProduct(Direction)>0 && HalfplaneIndicator<0)
    1670                                 {
    1671                                         TempNormal.Scale(-1);
    1672                                 }
    1673                 }
    1674 
    1675         TempNormal.Normalize();
    1676         Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius);
    1677         cout << Verbose(4) << "Height of center of circumference to center of sphere is " << Restradius << ".\n";
    1678         TempNormal.Scale(Restradius);
    1679         cout << Verbose(4) << "Shift vector to sphere of circumference is " << TempNormal << ".\n";
    1680 
    1681         Center->AddVector(&TempNormal);
    1682         cout << Verbose(0) << "Center of sphere of circumference is " << *Center << ".\n";
    1683         get_sphere(&OtherCenter, a, b, c, RADIUS);
    1684         cout << Verbose(0) << "OtherCenter of sphere of circumference is " << OtherCenter << ".\n";
    1685         cout << Verbose(3) << "End of Get_center_of_sphere.\n";
     1645    double HalfplaneIndicator, double AlternativeIndicator, double alpha, double beta, double gamma, double RADIUS, double Umkreisradius)
     1646{
     1647  Vector TempNormal, helper;
     1648  double Restradius;
     1649  Vector OtherCenter;
     1650  cout << Verbose(3) << "Begin of Get_center_of_sphere.\n";
     1651  Center->Zero();
     1652  helper.CopyVector(&a);
     1653  helper.Scale(sin(2.*alpha));
     1654  Center->AddVector(&helper);
     1655  helper.CopyVector(&b);
     1656  helper.Scale(sin(2.*beta));
     1657  Center->AddVector(&helper);
     1658  helper.CopyVector(&c);
     1659  helper.Scale(sin(2.*gamma));
     1660  Center->AddVector(&helper);
     1661  //*Center = a * sin(2.*alpha) + b * sin(2.*beta) + c * sin(2.*gamma) ;
     1662  Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));
     1663  NewUmkreismittelpunkt->CopyVector(Center);
     1664  cout << Verbose(4) << "Center of new circumference is " << *NewUmkreismittelpunkt << ".\n";
     1665  // Here we calculated center of circumscribing circle, using barycentric coordinates
     1666  cout << Verbose(4) << "Center of circumference is " << *Center << " in direction " << *Direction << ".\n";
     1667
     1668  TempNormal.CopyVector(&a);
     1669  TempNormal.SubtractVector(&b);
     1670  helper.CopyVector(&a);
     1671  helper.SubtractVector(&c);
     1672  TempNormal.VectorProduct(&helper);
     1673  if (fabs(HalfplaneIndicator) < MYEPSILON)
     1674    {
     1675      if ((TempNormal.ScalarProduct(AlternativeDirection) <0 and AlternativeIndicator >0) or (TempNormal.ScalarProduct(AlternativeDirection) >0 and AlternativeIndicator <0))
     1676        {
     1677          TempNormal.Scale(-1);
     1678        }
     1679    }
     1680  else
     1681    {
     1682      if (TempNormal.ScalarProduct(Direction)<0 && HalfplaneIndicator >0 || TempNormal.ScalarProduct(Direction)>0 && HalfplaneIndicator<0)
     1683        {
     1684          TempNormal.Scale(-1);
     1685        }
     1686    }
     1687  TempNormal.Normalize();
     1688  Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius);
     1689  cout << Verbose(4) << "Height of center of circumference to center of sphere is " << Restradius << ".\n";
     1690  TempNormal.Scale(Restradius);
     1691  cout << Verbose(4) << "Shift vector to sphere of circumference is " << TempNormal << ".\n";
     1692
     1693  Center->AddVector(&TempNormal);
     1694  cout << Verbose(0) << "Center of sphere of circumference is " << *Center << ".\n";
     1695  get_sphere(&OtherCenter, a, b, c, RADIUS);
     1696  cout << Verbose(0) << "OtherCenter of sphere of circumference is " << OtherCenter << ".\n";
     1697  cout << Verbose(3) << "End of Get_center_of_sphere.\n";
    16861698};
    16871699
    16881700/** This recursive function finds a third point, to form a triangle with two given ones.
    16891701 * Two atoms are fixed, a candidate is supplied, additionally two vectors for direction distinction, a Storage area to \
    1690  *      supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \
    1691  *      upon which we operate.
    1692  *      If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \
    1693  *      direction and angle into Storage.
    1694  *      We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \
    1695  *      with all neighbours of the candidate.
     1702 *  supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \
     1703 *  upon which we operate.
     1704 *  If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \
     1705 *  direction and angle into Storage.
     1706 *  We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \
     1707 *  with all neighbours of the candidate.
    16961708 * @param a first point
    16971709 * @param b second point
     
    17101722 */
    17111723void Tesselation::Find_next_suitable_point_via_Angle_of_Sphere(atom* a, atom* b, atom* c, atom* Candidate, atom* Parent,
    1712                 int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint,
    1713                 atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol)
    1714 {
    1715         cout << Verbose(2) << "Begin of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n";
    1716         cout << Verbose(3) << "Candidate is "<< *Candidate << endl;
    1717         cout << Verbose(4) << "Baseline vector is " << *Chord << "." << endl;
    1718         cout << Verbose(4) << "ReferencePoint is " << ReferencePoint << "." << endl;
    1719         cout << Verbose(4) << "Normal of base triangle is " << *OldNormal << "." << endl;
    1720         cout << Verbose(4) << "Search direction is " << *direction1 << "." << endl;
    1721         /* OldNormal is normal vector on the old triangle
    1722          * direction1 is normal on the triangle line, from which we come, as well as on OldNormal.
    1723          * Chord points from b to a!!!
    1724          */
    1725         Vector dif_a; //Vector from a to candidate
    1726         Vector dif_b; //Vector from b to candidate
    1727         Vector AngleCheck;
    1728         Vector TempNormal, Umkreismittelpunkt;
    1729         Vector Mittelpunkt;
    1730 
    1731         double CurrentEpsilon = 0.1;
    1732         double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius, Restradius, Distance;
    1733         double BallAngle, AlternativeSign;
    1734         atom *Walker; // variable atom point
    1735 
    1736         Vector NewUmkreismittelpunkt;
    1737 
    1738         if (a != Candidate and b != Candidate and c != Candidate) {
    1739                 cout << Verbose(3) << "We have a unique candidate!" << endl;
    1740                 dif_a.CopyVector(&(a->x));
    1741                 dif_a.SubtractVector(&(Candidate->x));
    1742                 dif_b.CopyVector(&(b->x));
    1743                 dif_b.SubtractVector(&(Candidate->x));
    1744                 AngleCheck.CopyVector(&(Candidate->x));
    1745                 AngleCheck.SubtractVector(&(a->x));
    1746                 AngleCheck.ProjectOntoPlane(Chord);
    1747 
    1748                 SideA = dif_b.Norm();
    1749                 SideB = dif_a.Norm();
    1750                 SideC = Chord->Norm();
    1751                 //Chord->Scale(-1);
    1752 
    1753                 alpha = Chord->Angle(&dif_a);
    1754                 beta = M_PI - Chord->Angle(&dif_b);
    1755                 gamma = dif_a.Angle(&dif_b);
    1756 
    1757                 cout << Verbose(2) << "Base triangle has sides " << dif_a << ", " << dif_b << ", " << *Chord << " with angles " << alpha/M_PI*180. << ", " << beta/M_PI*180. << ", " << gamma/M_PI*180. << "." << endl;
    1758 
    1759                 if (fabs(M_PI - alpha - beta - gamma) > MYEPSILON) {
    1760                         cerr << Verbose(0) << "WARNING: sum of angles for base triangle " << (alpha + beta + gamma)/M_PI*180. << " != 180.\n";
    1761                         cout << Verbose(1) << "Base triangle has sides " << dif_a << ", " << dif_b << ", " << *Chord << " with angles " << alpha/M_PI*180. << ", " << beta/M_PI*180. << ", " << gamma/M_PI*180. << "." << endl;
    1762                 }
    1763 
    1764                 if ((M_PI*179./180. > alpha) && (M_PI*179./180. > beta) && (M_PI*179./180. > gamma)) {
    1765                         Umkreisradius = SideA / 2.0 / sin(alpha);
    1766                         //cout << Umkreisradius << endl;
    1767                         //cout << SideB / 2.0 / sin(beta) << endl;
    1768                         //cout << SideC / 2.0 / sin(gamma) << endl;
    1769 
    1770                         if (Umkreisradius < RADIUS) { //Checking whether ball will at least rest on points.
    1771                                 cout << Verbose(3) << "Circle of circumference would fit: " << Umkreisradius << " < " << RADIUS << "." << endl;
    1772                                 cout << Verbose(2) << "Candidate is "<< *Candidate << endl;
    1773                                 sign = AngleCheck.ScalarProduct(direction1);
    1774                                 if (fabs(sign)<MYEPSILON) {
    1775                                         if (AngleCheck.ScalarProduct(OldNormal)<0) {
    1776                                                 sign =0;
    1777                                                 AlternativeSign=1;
    1778                                         } else {
    1779                                                 sign =0;
    1780                                                 AlternativeSign=-1;
    1781                                         }
    1782                                 } else {
    1783                                         sign /= fabs(sign);
    1784                                 }
    1785                                 if (sign >= 0) {
    1786                                         cout << Verbose(3) << "Candidate is in search direction: " << sign << "." << endl;
    1787                                         Get_center_of_sphere(&Mittelpunkt, (a->x), (b->x), (Candidate->x), &NewUmkreismittelpunkt, OldNormal, direction1, sign, AlternativeSign, alpha, beta, gamma, RADIUS, Umkreisradius);
    1788                                         Mittelpunkt.SubtractVector(&ReferencePoint);
    1789                                         cout << Verbose(3) << "Reference vector to sphere's center is " << Mittelpunkt << "." << endl;
    1790                                         BallAngle = Mittelpunkt.Angle(OldNormal);
    1791                                         cout << Verbose(3) << "Angle between normal of base triangle and center of ball sphere is :" << BallAngle << "." << endl;
    1792 
    1793                                         //cout << "direction1 is " << *direction1 << "." << endl;
    1794                                         //cout << "Mittelpunkt is " << Mittelpunkt << "."<< endl;
    1795                                         //cout << Verbose(3) << "BallAngle is " << BallAngle << " Sign is " << sign << endl;
    1796 
    1797                                         NewUmkreismittelpunkt.SubtractVector(&ReferencePoint);
    1798 
    1799                                         if ((Mittelpunkt.ScalarProduct(direction1) >=0) || (fabs(NewUmkreismittelpunkt.Norm()) < MYEPSILON)) {
    1800                                                 if (Storage[0]< -1.5) { // first Candidate at all
    1801                                                         if (1) {//if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) {
    1802                                                                 cout << Verbose(2) << "First good candidate is " << *Candidate << " with ";
    1803                                                                 Opt_Candidate = Candidate;
    1804                                                                 Storage[0] = sign;
    1805                                                                 Storage[1] = AlternativeSign;
    1806                                                                 Storage[2] = BallAngle;
    1807                                                                 cout << " angle " << Storage[2] << " and Up/Down " << Storage[0] << endl;
    1808                                                         } else
    1809                                                                 cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl;
    1810                                                 } else {
    1811                                                         if ( Storage[2] > BallAngle) {
    1812                                                                 if (1) { //if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) {
    1813                                                                         cout << Verbose(2) << "Next better candidate is " << *Candidate << " with ";
    1814                                                                         Opt_Candidate = Candidate;
    1815                                                                         Storage[0] = sign;
    1816                                                                         Storage[1] = AlternativeSign;
    1817                                                                         Storage[2] = BallAngle;
    1818                                                                         cout << " angle " << Storage[2] << " and Up/Down " << Storage[0] << endl;
    1819                                                                 } else
    1820                                                                         cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl;
    1821                                                         } else {
    1822                                                                 if (DEBUG) {
    1823                                                                         cout << Verbose(3) << *Candidate << " looses against better candidate " << *Opt_Candidate << "." << endl;
    1824                                                                 }
    1825                                                         }
    1826                                                 }
    1827                                         } else {
    1828                                                 if (DEBUG) {
    1829                                                         cout << Verbose(3) << *Candidate << " refused due to Up/Down sign which is " << sign << endl;
    1830                                                 }
    1831                                         }
    1832                                 } else {
    1833                                         if (DEBUG) {
    1834                                                 cout << Verbose(3) << *Candidate << " is not in search direction." << endl;
    1835                                         }
    1836                                 }
    1837                         } else {
    1838                                 if (DEBUG) {
    1839                                         cout << Verbose(3) << *Candidate << " would have circumference of " << Umkreisradius << " bigger than ball's radius " << RADIUS << "." << endl;
    1840                                 }
    1841                         }
    1842                 } else {
    1843                         if (DEBUG) {
    1844                                 cout << Verbose(0) << "Triangle consisting of " << *Candidate << ", " << *a << " and " << *b << " has an angle >150!" << endl;
    1845                         }
    1846                 }
    1847         } else {
    1848                 if (DEBUG) {
    1849                         cout << Verbose(3) << *Candidate << " is either " << *a << " or " << *b << "." << endl;
    1850                 }
    1851         }
    1852 
    1853         if (RecursionLevel < 5) { // Seven is the recursion level threshold.
    1854                 for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) { // go through all bond
    1855                         Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate);
    1856                         if (Walker == Parent) { // don't go back the same bond
    1857                                 continue;
    1858                         } else {
    1859                                 Find_next_suitable_point_via_Angle_of_Sphere(a, b, c, Walker, Candidate, RecursionLevel+1, Chord, direction1, OldNormal, ReferencePoint, Opt_Candidate, Storage, RADIUS, mol); //call function again
    1860                         }
    1861                 }
    1862         }
    1863         cout << Verbose(2) << "End of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n";
     1724    int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint,
     1725    atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol)
     1726{
     1727  cout << Verbose(2) << "Begin of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n";
     1728  cout << Verbose(3) << "Candidate is "<< *Candidate << endl;
     1729  cout << Verbose(4) << "Baseline vector is " << *Chord << "." << endl;
     1730  cout << Verbose(4) << "ReferencePoint is " << ReferencePoint << "." << endl;
     1731  cout << Verbose(4) << "Normal of base triangle is " << *OldNormal << "." << endl;
     1732  cout << Verbose(4) << "Search direction is " << *direction1 << "." << endl;
     1733  /* OldNormal is normal vector on the old triangle
     1734   * direction1 is normal on the triangle line, from which we come, as well as on OldNormal.
     1735   * Chord points from b to a!!!
     1736   */
     1737  Vector dif_a; //Vector from a to candidate
     1738  Vector dif_b; //Vector from b to candidate
     1739  Vector AngleCheck;
     1740  Vector TempNormal, Umkreismittelpunkt;
     1741  Vector Mittelpunkt;
     1742
     1743  double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius;
     1744  double BallAngle, AlternativeSign;
     1745  atom *Walker; // variable atom point
     1746
     1747  Vector NewUmkreismittelpunkt;
     1748
     1749  if (a != Candidate and b != Candidate and c != Candidate) {
     1750    cout << Verbose(3) << "We have a unique candidate!" << endl;
     1751    dif_a.CopyVector(&(a->x));
     1752    dif_a.SubtractVector(&(Candidate->x));
     1753    dif_b.CopyVector(&(b->x));
     1754    dif_b.SubtractVector(&(Candidate->x));
     1755    AngleCheck.CopyVector(&(Candidate->x));
     1756    AngleCheck.SubtractVector(&(a->x));
     1757    AngleCheck.ProjectOntoPlane(Chord);
     1758
     1759    SideA = dif_b.Norm();
     1760    SideB = dif_a.Norm();
     1761    SideC = Chord->Norm();
     1762    //Chord->Scale(-1);
     1763
     1764    alpha = Chord->Angle(&dif_a);
     1765    beta = M_PI - Chord->Angle(&dif_b);
     1766    gamma = dif_a.Angle(&dif_b);
     1767
     1768    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;
     1769
     1770    if (fabs(M_PI - alpha - beta - gamma) > MYEPSILON) {
     1771      cerr << Verbose(0) << "WARNING: sum of angles for base triangle " << (alpha + beta + gamma)/M_PI*180. << " != 180.\n";
     1772      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;
     1773    }
     1774
     1775    if ((M_PI*179./180. > alpha) && (M_PI*179./180. > beta) && (M_PI*179./180. > gamma)) {
     1776      Umkreisradius = SideA / 2.0 / sin(alpha);
     1777      //cout << Umkreisradius << endl;
     1778      //cout << SideB / 2.0 / sin(beta) << endl;
     1779      //cout << SideC / 2.0 / sin(gamma) << endl;
     1780
     1781      if (Umkreisradius < RADIUS) { //Checking whether ball will at least rest on points.
     1782        cout << Verbose(3) << "Circle of circumference would fit: " << Umkreisradius << " < " << RADIUS << "." << endl;
     1783        cout << Verbose(2) << "Candidate is "<< *Candidate << endl;
     1784        sign = AngleCheck.ScalarProduct(direction1);
     1785        if (fabs(sign)<MYEPSILON) {
     1786          if (AngleCheck.ScalarProduct(OldNormal)<0) {
     1787            sign =0;
     1788            AlternativeSign=1;
     1789          } else {
     1790            sign =0;
     1791            AlternativeSign=-1;
     1792          }
     1793        } else {
     1794          sign /= fabs(sign);
     1795          cout << Verbose(3) << "Candidate is in search direction: " << sign << "." << endl;
     1796        }
     1797        if (sign >= 0) {
     1798          cout << Verbose(3) << "Candidate is in search direction: " << sign << "." << endl;
     1799          Get_center_of_sphere(&Mittelpunkt, (a->x), (b->x), (Candidate->x), &NewUmkreismittelpunkt, OldNormal, direction1, sign, AlternativeSign, alpha, beta, gamma, RADIUS, Umkreisradius);
     1800          Mittelpunkt.SubtractVector(&ReferencePoint);
     1801          cout << Verbose(3) << "Reference vector to sphere's center is " << Mittelpunkt << "." << endl;
     1802          BallAngle = Mittelpunkt.Angle(OldNormal);
     1803          cout << Verbose(3) << "Angle between normal of base triangle and center of ball sphere is :" << BallAngle << "." << endl;
     1804
     1805
     1806        cout << Verbose(3) << "BallAngle is " << BallAngle << " Sign is " << sign << endl;
     1807
     1808          if ((Mittelpunkt.ScalarProduct(direction1) >=0) || (fabs(NewUmkreismittelpunkt.Norm()) < MYEPSILON)) {
     1809            if (Storage[0]< -1.5) { // first Candidate at all
     1810              if (1) {//if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) {
     1811                cout << Verbose(2) << "First good 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 ( Storage[2] > BallAngle) {
     1821                if (1) { //if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) {
     1822                  cout << Verbose(2) << "Next better candidate is " << *Candidate << " with ";
     1823                  Opt_Candidate = Candidate;
     1824                  Storage[0] = sign;
     1825                  Storage[1] = AlternativeSign;
     1826                  Storage[2] = BallAngle;
     1827                  cout << " angle " << Storage[2] << " and Up/Down " << Storage[0] << endl;
     1828                } else
     1829                  cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl;
     1830              } else {
     1831                if (DEBUG) {
     1832                  cout << Verbose(3) << *Candidate << " looses against better candidate " << *Opt_Candidate << "." << endl;
     1833                }
     1834              }
     1835            }
     1836          } else {
     1837            if (DEBUG) {
     1838              cout << Verbose(3) << *Candidate << " refused due to Up/Down sign which is " << sign << endl;
     1839            }
     1840          }
     1841        } else {
     1842          if (DEBUG) {
     1843            cout << Verbose(3) << *Candidate << " is not in search direction." << endl;
     1844          }
     1845        }
     1846      } else {
     1847        if (DEBUG) {
     1848          cout << Verbose(3) << *Candidate << " would have circumference of " << Umkreisradius << " bigger than ball's radius " << RADIUS << "." << endl;
     1849        }
     1850      }
     1851    } else {
     1852      if (DEBUG) {
     1853        cout << Verbose(0) << "Triangle consisting of " << *Candidate << ", " << *a << " and " << *b << " has an angle >150!" << endl;
     1854      }
     1855    }
     1856  } else {
     1857    if (DEBUG) {
     1858      cout << Verbose(3) << *Candidate << " is either " << *a << " or " << *b << "." << endl;
     1859    }
     1860  }
     1861
     1862  if (RecursionLevel < 5) { // Seven is the recursion level threshold.
     1863    for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) { // go through all bond
     1864      Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate);
     1865      if (Walker == Parent) { // don't go back the same bond
     1866        continue;
     1867      } else {
     1868        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
     1869      }
     1870    }
     1871  }
     1872  cout << Verbose(2) << "End of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n";
    18641873}
    18651874;
     
    18741883void GetCenterofCircumcircle(Vector *Center, Vector *a, Vector *b, Vector *c)
    18751884{
    1876         Vector helper;
    1877         double alpha, beta, gamma;
    1878         Vector SideA, SideB, SideC;
    1879         SideA.CopyVector(b);
    1880         SideA.SubtractVector(c);
    1881         SideB.CopyVector(c);
    1882         SideB.SubtractVector(a);
    1883         SideC.CopyVector(a);
    1884         SideC.SubtractVector(b);
    1885         alpha = M_PI - SideB.Angle(&SideC);
    1886         beta = M_PI - SideC.Angle(&SideA);
    1887         gamma = M_PI - SideA.Angle(&SideB);
    1888         cout << Verbose(3) << "INFO: alpha = " << alpha/M_PI*180. << ", beta = " << beta/M_PI*180. << ", gamma = " << gamma/M_PI*180. << "." << endl;
    1889         if (fabs(M_PI - alpha - beta - gamma) > HULLEPSILON)
    1890                 cerr << "Sum of angles " << (alpha+beta+gamma)/M_PI*180. << " > 180 degrees by " << fabs(M_PI - alpha - beta - gamma)/M_PI*180. << "!" << endl;
    1891 
    1892         Center->Zero();
    1893         helper.CopyVector(a);
    1894         helper.Scale(sin(2.*alpha));
    1895         Center->AddVector(&helper);
    1896         helper.CopyVector(b);
    1897         helper.Scale(sin(2.*beta));
    1898         Center->AddVector(&helper);
    1899         helper.CopyVector(c);
    1900         helper.Scale(sin(2.*gamma));
    1901         Center->AddVector(&helper);
    1902         Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));
     1885  Vector helper;
     1886  double alpha, beta, gamma;
     1887  Vector SideA, SideB, SideC;
     1888  SideA.CopyVector(b);
     1889  SideA.SubtractVector(c);
     1890  SideB.CopyVector(c);
     1891  SideB.SubtractVector(a);
     1892  SideC.CopyVector(a);
     1893  SideC.SubtractVector(b);
     1894  alpha = M_PI - SideB.Angle(&SideC);
     1895  beta = M_PI - SideC.Angle(&SideA);
     1896  gamma = M_PI - SideA.Angle(&SideB);
     1897  cout << Verbose(3) << "INFO: alpha = " << alpha/M_PI*180. << ", beta = " << beta/M_PI*180. << ", gamma = " << gamma/M_PI*180. << "." << endl;
     1898  if (fabs(M_PI - alpha - beta - gamma) > HULLEPSILON)
     1899    cerr << "Sum of angles " << (alpha+beta+gamma)/M_PI*180. << " > 180 degrees by " << fabs(M_PI - alpha - beta - gamma)/M_PI*180. << "!" << endl;
     1900
     1901  Center->Zero();
     1902  helper.CopyVector(a);
     1903  helper.Scale(sin(2.*alpha));
     1904  Center->AddVector(&helper);
     1905  helper.CopyVector(b);
     1906  helper.Scale(sin(2.*beta));
     1907  Center->AddVector(&helper);
     1908  helper.CopyVector(c);
     1909  helper.Scale(sin(2.*gamma));
     1910  Center->AddVector(&helper);
     1911  Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));
    19031912};
    19041913
     
    19181927double GetPathLengthonCircumCircle(Vector &CircleCenter, Vector &CirclePlaneNormal, double CircleRadius, Vector &NewSphereCenter, Vector &OldSphereCenter, Vector &NormalVector, Vector &SearchDirection)
    19191928{
    1920         Vector helper;
    1921         double radius, alpha;
    1922 
    1923         helper.CopyVector(&NewSphereCenter);
    1924         // test whether new center is on the parameter circle's plane
    1925         if (fabs(helper.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
    1926                 cerr << "ERROR: Something's very wrong here: NewSphereCenter is not on the band's plane as desired by " <<fabs(helper.ScalarProduct(&CirclePlaneNormal))        << "!" << endl;
    1927                 helper.ProjectOntoPlane(&CirclePlaneNormal);
    1928         }
    1929         radius = helper.ScalarProduct(&helper);
    1930         // test whether the new center vector has length of CircleRadius
    1931         if (fabs(radius - CircleRadius) > HULLEPSILON)
    1932                 cerr << Verbose(1) << "ERROR: The projected center of the new sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
    1933         alpha = helper.Angle(&OldSphereCenter);
    1934         // make the angle unique by checking the halfplanes/search direction
    1935         if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)      // acos is not unique on [0, 2.*M_PI), hence extra check to decide between two half intervals
    1936                 alpha = 2.*M_PI - alpha;
    1937         cout << Verbose(2) << "INFO: RelativeNewSphereCenter is " << helper << ", RelativeOldSphereCenter is " << OldSphereCenter << " and resulting angle is " << alpha << "." << endl;
    1938         radius = helper.Distance(&OldSphereCenter);
    1939         helper.ProjectOntoPlane(&NormalVector);
    1940         // check whether new center is somewhat away or at least right over the current baseline to prevent intersecting triangles
    1941         if ((radius > HULLEPSILON) || (helper.Norm() < HULLEPSILON)) {
    1942                 cout << Verbose(2) << "INFO: Distance between old and new center is " << radius << " and between new center and baseline center is " << helper.Norm() << "." << endl;
    1943                 return alpha;
    1944         } else {
    1945                 cout << Verbose(1) << "ERROR: NewSphereCenter " << helper << " is too close to OldSphereCenter" << OldSphereCenter << "." << endl;
    1946                 return 2.*M_PI;
    1947         }
     1929  Vector helper;
     1930  double radius, alpha;
     1931
     1932  helper.CopyVector(&NewSphereCenter);
     1933  // test whether new center is on the parameter circle's plane
     1934  if (fabs(helper.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
     1935    cerr << "ERROR: Something's very wrong here: NewSphereCenter is not on the band's plane as desired by " <<fabs(helper.ScalarProduct(&CirclePlaneNormal))  << "!" << endl;
     1936    helper.ProjectOntoPlane(&CirclePlaneNormal);
     1937  }
     1938  radius = helper.ScalarProduct(&helper);
     1939  // test whether the new center vector has length of CircleRadius
     1940  if (fabs(radius - CircleRadius) > HULLEPSILON)
     1941    cerr << Verbose(1) << "ERROR: The projected center of the new sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
     1942  alpha = helper.Angle(&OldSphereCenter);
     1943  // make the angle unique by checking the halfplanes/search direction
     1944  if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)  // acos is not unique on [0, 2.*M_PI), hence extra check to decide between two half intervals
     1945    alpha = 2.*M_PI - alpha;
     1946  cout << Verbose(2) << "INFO: RelativeNewSphereCenter is " << helper << ", RelativeOldSphereCenter is " << OldSphereCenter << " and resulting angle is " << alpha << "." << endl;
     1947  radius = helper.Distance(&OldSphereCenter);
     1948  helper.ProjectOntoPlane(&NormalVector);
     1949  // check whether new center is somewhat away or at least right over the current baseline to prevent intersecting triangles
     1950  if ((radius > HULLEPSILON) || (helper.Norm() < HULLEPSILON)) {
     1951    cout << Verbose(2) << "INFO: Distance between old and new center is " << radius << " and between new center and baseline center is " << helper.Norm() << "." << endl;
     1952    return alpha;
     1953  } else {
     1954    cout << Verbose(1) << "ERROR: NewSphereCenter " << helper << " is too close to OldSphereCenter" << OldSphereCenter << "." << endl;
     1955    return 2.*M_PI;
     1956  }
    19481957};
    19491958
     
    19801989// void Find_next_suitable_point(class BoundaryTriangleSet *BaseTriangle, class BoundaryLineSet *BaseLine, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC)
    19811990// {
    1982 //      atom *Walker = NULL;
    1983 //       Vector CircleCenter;   // center of the circle, i.e. of the band of sphere's centers
    1984 //      Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in
    1985 //       Vector OldSphereCenter;        // center of the sphere defined by the three points of BaseTriangle
    1986 //       Vector NewSphereCenter;        // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility
    1987 //       Vector OtherNewSphereCenter;    // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility
    1988 //       Vector NewNormalVector;        // normal vector of the Candidate's triangle
    1989 //       Vector SearchDirection;        // vector that points out of BaseTriangle and is orthonormal to its NormalVector (i.e. the desired direction for the best Candidate)
    1990 //      Vector helper;
    1991 //      LinkedAtoms *List = NULL;
    1992 //      double CircleRadius; // radius of this circle
    1993 //      double radius;
    1994 //      double alpha, Otheralpha; // angles (i.e. parameter for the circle).
    1995 //      double Nullalpha; // angle between OldSphereCenter and NormalVector of base triangle
    1996 //      int N[NDIM], Nlower[NDIM], Nupper[NDIM];
    1997 //      atom *Candidate = NULL;
     1991//  atom *Walker = NULL;
     1992//   Vector CircleCenter;  // center of the circle, i.e. of the band of sphere's centers
     1993//  Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in
     1994//   Vector OldSphereCenter;  // center of the sphere defined by the three points of BaseTriangle
     1995//   Vector NewSphereCenter;  // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility
     1996//   Vector OtherNewSphereCenter;  // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility
     1997//   Vector NewNormalVector;  // normal vector of the Candidate's triangle
     1998//   Vector SearchDirection;  // vector that points out of BaseTriangle and is orthonormal to its NormalVector (i.e. the desired direction for the best Candidate)
     1999//  Vector helper;
     2000//  LinkedAtoms *List = NULL;
     2001//  double CircleRadius; // radius of this circle
     2002//  double radius;
     2003//  double alpha, Otheralpha; // angles (i.e. parameter for the circle).
     2004//  double Nullalpha; // angle between OldSphereCenter and NormalVector of base triangle
     2005//  int N[NDIM], Nlower[NDIM], Nupper[NDIM];
     2006//  atom *Candidate = NULL;
    19982007//
    1999 //      cout << Verbose(1) << "Begin of Find_next_suitable_point" << endl;
     2008//  cout << Verbose(1) << "Begin of Find_next_suitable_point" << endl;
    20002009//
    2001 //      cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << BaseTriangle->NormalVector << "." << endl;
     2010//  cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << BaseTriangle->NormalVector << "." << endl;
    20022011//
    2003 //      // construct center of circle
    2004 //      CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x));
    2005 //      CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x);
    2006 //      CircleCenter.Scale(0.5);
     2012//  // construct center of circle
     2013//  CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x));
     2014//  CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x);
     2015//  CircleCenter.Scale(0.5);
    20072016//
    2008 //      // construct normal vector of circle
    2009 //      CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x);
    2010 //      CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x);
     2017//  // construct normal vector of circle
     2018//  CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x);
     2019//  CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x);
    20112020//
    2012 //      // calculate squared radius of circle
    2013 //      radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
    2014 //      if (radius/4. < RADIUS*RADIUS) {
    2015 //              CircleRadius = RADIUS*RADIUS - radius/4.;
    2016 //              CirclePlaneNormal.Normalize();
    2017 //              cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
     2021//  // calculate squared radius of circle
     2022//  radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
     2023//  if (radius/4. < RADIUS*RADIUS) {
     2024//    CircleRadius = RADIUS*RADIUS - radius/4.;
     2025//    CirclePlaneNormal.Normalize();
     2026//    cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
    20182027//
    2019 //              // construct old center
    2020 //              GetCenterofCircumcircle(&OldSphereCenter, &(BaseTriangle->endpoints[0]->node->x), &(BaseTriangle->endpoints[1]->node->x), &(BaseTriangle->endpoints[2]->node->x));
    2021 //               helper.CopyVector(&BaseTriangle->NormalVector);        // normal vector ensures that this is correct center of the two possible ones
    2022 //              radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&OldSphereCenter);
    2023 //              helper.Scale(sqrt(RADIUS*RADIUS - radius));
    2024 //              OldSphereCenter.AddVector(&helper);
    2025 //              OldSphereCenter.SubtractVector(&CircleCenter);
    2026 //              cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;
     2028//    // construct old center
     2029//    GetCenterofCircumcircle(&OldSphereCenter, &(BaseTriangle->endpoints[0]->node->x), &(BaseTriangle->endpoints[1]->node->x), &(BaseTriangle->endpoints[2]->node->x));
     2030//     helper.CopyVector(&BaseTriangle->NormalVector);  // normal vector ensures that this is correct center of the two possible ones
     2031//    radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&OldSphereCenter);
     2032//    helper.Scale(sqrt(RADIUS*RADIUS - radius));
     2033//    OldSphereCenter.AddVector(&helper);
     2034//    OldSphereCenter.SubtractVector(&CircleCenter);
     2035//    cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;
    20272036//
    2028 //              // test whether old center is on the band's plane
    2029 //              if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
    2030 //                      cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl;
    2031 //                      OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal);
    2032 //              }
    2033 //              radius = OldSphereCenter.ScalarProduct(&OldSphereCenter);
    2034 //              if (fabs(radius - CircleRadius) < HULLEPSILON) {
     2037//    // test whether old center is on the band's plane
     2038//    if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
     2039//      cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl;
     2040//      OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal);
     2041//    }
     2042//    radius = OldSphereCenter.ScalarProduct(&OldSphereCenter);
     2043//    if (fabs(radius - CircleRadius) < HULLEPSILON) {
    20352044//
    2036 //                      // construct SearchDirection
    2037 //                      SearchDirection.MakeNormalVector(&BaseTriangle->NormalVector, &CirclePlaneNormal);
    2038 //                      helper.CopyVector(&BaseLine->endpoints[0]->node->x);
    2039 //                       for(int i=0;i<3;i++)   // just take next different endpoint
    2040 //                              if ((BaseTriangle->endpoints[i]->node != BaseLine->endpoints[0]->node) && (BaseTriangle->endpoints[i]->node != BaseLine->endpoints[1]->node)) {
    2041 //                                      helper.SubtractVector(&BaseTriangle->endpoints[i]->node->x);
    2042 //                              }
    2043 //                       if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)     // ohoh, SearchDirection points inwards!
    2044 //                              SearchDirection.Scale(-1.);
    2045 //                      SearchDirection.ProjectOntoPlane(&OldSphereCenter);
    2046 //                      SearchDirection.Normalize();
    2047 //                      cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
    2048 //                       if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {     // rotated the wrong way!
    2049 //                              cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl;
    2050 //                      }
     2045//      // construct SearchDirection
     2046//      SearchDirection.MakeNormalVector(&BaseTriangle->NormalVector, &CirclePlaneNormal);
     2047//      helper.CopyVector(&BaseLine->endpoints[0]->node->x);
     2048//       for(int i=0;i<3;i++)  // just take next different endpoint
     2049//        if ((BaseTriangle->endpoints[i]->node != BaseLine->endpoints[0]->node) && (BaseTriangle->endpoints[i]->node != BaseLine->endpoints[1]->node)) {
     2050//          helper.SubtractVector(&BaseTriangle->endpoints[i]->node->x);
     2051//        }
     2052//       if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)  // ohoh, SearchDirection points inwards!
     2053//        SearchDirection.Scale(-1.);
     2054//      SearchDirection.ProjectOntoPlane(&OldSphereCenter);
     2055//      SearchDirection.Normalize();
     2056//      cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
     2057//       if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {  // rotated the wrong way!
     2058//        cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl;
     2059//      }
    20512060//
    2052 //                       if (LC->SetIndexToVector(&CircleCenter)) {     // get cell for the starting atom
    2053 //                              for(int i=0;i<NDIM;i++) // store indices of this cell
    2054 //                                      N[i] = LC->n[i];
    2055 //                              cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
    2056 //                      } else {
    2057 //                              cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl;
    2058 //                              return;
    2059 //                      }
    2060 //                      // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
    2061 //                      cout << Verbose(2) << "LC Intervals:";
    2062 //                      for (int i=0;i<NDIM;i++) {
    2063 //                              Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
    2064 //                              Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
    2065 //                              cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
    2066 //                      }
    2067 //                      cout << endl;
    2068 //                      for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
    2069 //                              for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
    2070 //                                      for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
    2071 //                                              List = LC->GetCurrentCell();
    2072 //                                              cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
    2073 //                                              if (List != NULL) {
    2074 //                                                      for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
    2075 //                                                              Candidate = (*Runner);
     2061//       if (LC->SetIndexToVector(&CircleCenter)) {  // get cell for the starting atom
     2062//        for(int i=0;i<NDIM;i++) // store indices of this cell
     2063//          N[i] = LC->n[i];
     2064//        cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
     2065//      } else {
     2066//        cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl;
     2067//        return;
     2068//      }
     2069//      // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
     2070//      cout << Verbose(2) << "LC Intervals:";
     2071//      for (int i=0;i<NDIM;i++) {
     2072//        Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
     2073//        Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
     2074//        cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
     2075//      }
     2076//      cout << endl;
     2077//      for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
     2078//        for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
     2079//          for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
     2080//            List = LC->GetCurrentCell();
     2081//            cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
     2082//            if (List != NULL) {
     2083//              for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
     2084//                Candidate = (*Runner);
    20762085//
    2077 //                                                              // check for three unique points
    2078 //                                                              if ((Candidate != BaseTriangle->endpoints[0]->node) && (Candidate != BaseTriangle->endpoints[1]->node) && (Candidate != BaseTriangle->endpoints[2]->node)) {
    2079 //                                                                      cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl;
     2086//                // check for three unique points
     2087//                if ((Candidate != BaseTriangle->endpoints[0]->node) && (Candidate != BaseTriangle->endpoints[1]->node) && (Candidate != BaseTriangle->endpoints[2]->node)) {
     2088//                  cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl;
    20802089//
    2081 //                                                                      // construct both new centers
    2082 //                                                                      GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x));
    2083 //                                                                      OtherNewSphereCenter.CopyVector(&NewSphereCenter);
     2090//                  // construct both new centers
     2091//                  GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x));
     2092//                  OtherNewSphereCenter.CopyVector(&NewSphereCenter);
    20842093//
    2085 //                                                                      if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) {
    2086 //                                                                              helper.CopyVector(&NewNormalVector);
    2087 //                                                                              cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl;
    2088 //                                                                              radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter);
    2089 //                                                                              if (radius < RADIUS*RADIUS) {
    2090 //                                                                                      helper.Scale(sqrt(RADIUS*RADIUS - radius));
    2091 //                                                                                      cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl;
    2092 //                                                                                      NewSphereCenter.AddVector(&helper);
    2093 //                                                                                      NewSphereCenter.SubtractVector(&CircleCenter);
    2094 //                                                                                      cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl;
     2094//                  if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) {
     2095//                    helper.CopyVector(&NewNormalVector);
     2096//                    cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl;
     2097//                    radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter);
     2098//                    if (radius < RADIUS*RADIUS) {
     2099//                      helper.Scale(sqrt(RADIUS*RADIUS - radius));
     2100//                      cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl;
     2101//                      NewSphereCenter.AddVector(&helper);
     2102//                      NewSphereCenter.SubtractVector(&CircleCenter);
     2103//                      cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl;
    20952104//
    2096 //                                                                                      helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction
    2097 //                                                                                      OtherNewSphereCenter.AddVector(&helper);
    2098 //                                                                                      OtherNewSphereCenter.SubtractVector(&CircleCenter);
    2099 //                                                                                      cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl;
     2105//                      helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction
     2106//                      OtherNewSphereCenter.AddVector(&helper);
     2107//                      OtherNewSphereCenter.SubtractVector(&CircleCenter);
     2108//                      cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl;
    21002109//
    2101 //                                                                                      // check both possible centers
    2102 //                                                                                      alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection);
    2103 //                                                                                      Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection);
    2104 //                                                                                      alpha = min(alpha, Otheralpha);
    2105 //                                                                                      if (*ShortestAngle > alpha) {
    2106 //                                                                                                      OptCandidate = Candidate;
    2107 //                                                                                                      *ShortestAngle = alpha;
    2108 //                                                                                                      if (alpha != Otheralpha)
    2109 //                                                                                                              OptCandidateCenter->CopyVector(&NewSphereCenter);
    2110 //                                                                                                      else
    2111 //                                                                                                              OptCandidateCenter->CopyVector(&OtherNewSphereCenter);
    2112 //                                                                                                      cout << Verbose(1) << "We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl;
    2113 //                                                                                      } else {
    2114 //                                                                                              if (OptCandidate != NULL)
    2115 //                                                                                                      cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl;
    2116 //                                                                                              else
    2117 //                                                                                                      cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl;
    2118 //                                                                                      }
     2110//                      // check both possible centers
     2111//                      alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection);
     2112//                      Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection);
     2113//                      alpha = min(alpha, Otheralpha);
     2114//                      if (*ShortestAngle > alpha) {
     2115//                          OptCandidate = Candidate;
     2116//                          *ShortestAngle = alpha;
     2117//                          if (alpha != Otheralpha)
     2118//                            OptCandidateCenter->CopyVector(&NewSphereCenter);
     2119//                          else
     2120//                            OptCandidateCenter->CopyVector(&OtherNewSphereCenter);
     2121//                          cout << Verbose(1) << "We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl;
     2122//                      } else {
     2123//                        if (OptCandidate != NULL)
     2124//                          cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl;
     2125//                        else
     2126//                          cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl;
     2127//                      }
    21192128//
    2120 //                                                                              } else {
    2121 //                                                                                      cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl;
    2122 //                                                                              }
    2123 //                                                                      } else {
    2124 //                                                                              cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl;
    2125 //                                                                      }
    2126 //                                                              } else {
    2127 //                                                                      cout << Verbose(1) << "REJECT: Base triangle " << *BaseTriangle << " contains Candidate " << *Candidate << "." << endl;
    2128 //                                                              }
    2129 //                                                      }
    2130 //                                              }
    2131 //                                      }
    2132 //              } else {
    2133 //                      cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
    2134 //              }
    2135 //      } else {
    2136 //              cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and base triangle " << *BaseTriangle << " is too big!" << endl;
    2137 //      }
     2129//                    } else {
     2130//                      cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl;
     2131//                    }
     2132//                  } else {
     2133//                    cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl;
     2134//                  }
     2135//                } else {
     2136//                  cout << Verbose(1) << "REJECT: Base triangle " << *BaseTriangle << " contains Candidate " << *Candidate << "." << endl;
     2137//                }
     2138//              }
     2139//            }
     2140//          }
     2141//    } else {
     2142//      cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
     2143//    }
     2144//  } else {
     2145//    cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and base triangle " << *BaseTriangle << " is too big!" << endl;
     2146//  }
    21382147//
    2139 //      cout << Verbose(1) << "End of Find_next_suitable_point" << endl;
     2148//  cout << Verbose(1) << "End of Find_next_suitable_point" << endl;
    21402149// };
    21412150
    2142 
    2143 /** Checks whether the triangle consisting of the three atoms is already present.
    2144  * Searches for the points in Tesselation::PointsOnBoundary and checks their
    2145  * lines. If any of the three edges already has two triangles attached, false is
    2146  * returned.
    2147  * \param *out output stream for debugging
    2148  * \param *Candidates endpoints of the triangle candidate
    2149  * \return false - triangle invalid due to edge criteria, true - triangle may be added.
    2150  */
    2151 bool Tesselation::CheckPresenceOfTriangle(ofstream *out, atom *Candidates[3]) {
    2152         LineMap::iterator FindLine;
    2153         PointMap::iterator FindPoint;
    2154         bool Present[3];
    2155 
    2156         *out << Verbose(2) << "Begin of CheckPresenceOfTriangle" << endl;
    2157         for (int i=0;i<3;i++) { // check through all endpoints
    2158                 FindPoint = PointsOnBoundary.find(Candidates[i]->nr);
    2159                 if (FindPoint != PointsOnBoundary.end())
    2160                         TPS[i] = FindPoint->second;
    2161                 else
    2162                         TPS[i] = NULL;
    2163         }
    2164 
    2165         // check lines
    2166         for (int i=0;i<3;i++)
    2167                 if (TPS[i] != NULL)
    2168                         for (int j=i;j<3;j++)
    2169                                 if (TPS[j] != NULL) {
    2170                                         FindLine = TPS[i]->lines.find(TPS[j]->node->nr);
    2171                                         if ((FindLine != TPS[i]->lines.end()) && (FindLine->second->TrianglesCount > 1)) {
    2172                                                 *out << "WARNING: Line " << *FindLine->second << " already present with " << FindLine->second->TrianglesCount << " triangles attached." << endl;
    2173                                                 *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;
    2174                                                 return false;
    2175                                         }
    2176                                 }
    2177         *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;
    2178         return true;
    2179 };
    21802151
    21812152/** This recursive function finds a third point, to form a triangle with two given ones.
     
    22142185void 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)
    22152186{
    2216         atom *Walker = NULL;
    2217         Vector CircleCenter;    // center of the circle, i.e. of the band of sphere's centers
    2218         Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in
    2219         Vector NewSphereCenter;  // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility
    2220         Vector OtherNewSphereCenter;     // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility
    2221         Vector NewNormalVector;  // normal vector of the Candidate's triangle
    2222         Vector helper;
    2223         LinkedAtoms *List = NULL;
    2224         double CircleRadius; // radius of this circle
    2225         double radius;
    2226         double alpha, Otheralpha; // angles (i.e. parameter for the circle).
    2227         double Nullalpha; // angle between OldSphereCenter and NormalVector of base triangle
    2228         int N[NDIM], Nlower[NDIM], Nupper[NDIM];
    2229         atom *Candidate = NULL;
    2230 
    2231         cout << Verbose(1) << "Begin of Find_third_point_for_Tesselation" << endl;
    2232 
    2233         cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl;
    2234 
    2235         // construct center of circle
    2236         CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x));
    2237         CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x);
    2238         CircleCenter.Scale(0.5);
    2239 
    2240         // construct normal vector of circle
    2241         CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x);
    2242         CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x);
    2243 
    2244         // calculate squared radius of circle
    2245         radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
    2246         if (radius/4. < RADIUS*RADIUS) {
    2247                 CircleRadius = RADIUS*RADIUS - radius/4.;
    2248                 CirclePlaneNormal.Normalize();
    2249                 cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
    2250 
    2251                 // test whether old center is on the band's plane
    2252                 if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
    2253                         cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl;
    2254                         OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal);
    2255                 }
    2256                 radius = OldSphereCenter.ScalarProduct(&OldSphereCenter);
    2257                 if (fabs(radius - CircleRadius) < HULLEPSILON) {
    2258 
    2259                         // check SearchDirection
    2260                         cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
    2261                         if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {      // rotated the wrong way!
    2262                                 cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are not orthogonal!" << endl;
    2263                         }
    2264                         // get cell for the starting atom
    2265                         if (LC->SetIndexToVector(&CircleCenter)) {
    2266                                         for(int i=0;i<NDIM;i++) // store indices of this cell
    2267                                         N[i] = LC->n[i];
    2268                                 cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
    2269                         } else {
    2270                                 cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl;
    2271                                 return;
    2272                         }
    2273                         // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
    2274                         cout << Verbose(2) << "LC Intervals:";
    2275                         for (int i=0;i<NDIM;i++) {
    2276                                 Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
    2277                                 Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
    2278                                 cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
    2279                         }
    2280                         cout << endl;
    2281                         for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
    2282                                 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
    2283                                         for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
    2284                                                 List = LC->GetCurrentCell();
    2285                                                 //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
    2286                                                 if (List != NULL) {
    2287                                                         for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
    2288                                                                 Candidate = (*Runner);
    2289 
    2290                                                                 // check for three unique points
    2291                                                                 if ((Candidate != BaseLine->endpoints[0]->node) && (Candidate != BaseLine->endpoints[1]->node) && (Candidate != ThirdNode)) {
    2292                                                                         cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl;
    2293 
    2294                                                                         // construct both new centers
    2295                                                                         GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x));
    2296                                                                         OtherNewSphereCenter.CopyVector(&NewSphereCenter);
    2297 
    2298                                                                         if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) {
    2299                                                                                 helper.CopyVector(&NewNormalVector);
    2300                                                                                 cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl;
    2301                                                                                 radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter);
    2302                                                                                 if (radius < RADIUS*RADIUS) {
    2303                                                                                         helper.Scale(sqrt(RADIUS*RADIUS - radius));
    2304                                                                                         cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl;
    2305                                                                                         NewSphereCenter.AddVector(&helper);
    2306                                                                                         NewSphereCenter.SubtractVector(&CircleCenter);
    2307                                                                                         cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl;
    2308 
    2309                                                                                         helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction
    2310                                                                                         OtherNewSphereCenter.AddVector(&helper);
    2311                                                                                         OtherNewSphereCenter.SubtractVector(&CircleCenter);
    2312                                                                                         cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl;
    2313 
    2314                                                                                         // check both possible centers
    2315                                                                                         alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, NormalVector, SearchDirection);
    2316                                                                                         Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, NormalVector, SearchDirection);
    2317                                                                                         alpha = min(alpha, Otheralpha);
    2318                                                                                         if (*ShortestAngle > alpha) {
    2319                                                                                                         OptCandidate = Candidate;
    2320                                                                                                         *ShortestAngle = alpha;
    2321                                                                                                         if (alpha != Otheralpha)
    2322                                                                                                                 OptCandidateCenter->CopyVector(&NewSphereCenter);
    2323                                                                                                         else
    2324                                                                                                                 OptCandidateCenter->CopyVector(&OtherNewSphereCenter);
    2325                                                                                                         cout << Verbose(1) << "ACCEPT: We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl;
    2326                                                                                         } else {
    2327                                                                                                 if (OptCandidate != NULL)
    2328                                                                                                         cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl;
    2329                                                                                                 else
    2330                                                                                                         cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl;
    2331                                                                                         }
    2332 
    2333                                                                                 } else {
    2334                                                                                         cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl;
    2335                                                                                 }
    2336                                                                         } else {
    2337                                                                                 cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl;
    2338                                                                         }
    2339                                                                 } else {
    2340                                                                         if (ThirdNode != NULL)
    2341                                                                                 cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " and " << *ThirdNode << " contains Candidate " << *Candidate << "." << endl;
    2342                                                                         else
    2343                                                                                 cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " contains Candidate " << *Candidate << "." << endl;
    2344                                                                 }
    2345                                                         }
    2346                                                 }
    2347                                         }
    2348                 } else {
    2349                         cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
    2350                 }
    2351         } else {
    2352                 if (ThirdNode != NULL)
    2353                         cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and third node " << *ThirdNode << " is too big!" << endl;
    2354                 else
    2355                         cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " is too big!" << endl;
    2356         }
    2357 
    2358         cout << Verbose(1) << "End of Find_third_point_for_Tesselation" << endl;
     2187  Vector CircleCenter;  // center of the circle, i.e. of the band of sphere's centers
     2188  Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in
     2189  Vector NewSphereCenter;   // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility
     2190  Vector OtherNewSphereCenter;   // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility
     2191  Vector NewNormalVector;   // normal vector of the Candidate's triangle
     2192  Vector helper;
     2193  LinkedAtoms *List = NULL;
     2194  double CircleRadius; // radius of this circle
     2195  double radius;
     2196  double alpha, Otheralpha; // angles (i.e. parameter for the circle).
     2197  int N[NDIM], Nlower[NDIM], Nupper[NDIM];
     2198  atom *Candidate = NULL;
     2199
     2200  cout << Verbose(1) << "Begin of Find_third_point_for_Tesselation" << endl;
     2201
     2202  cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl;
     2203
     2204  // construct center of circle
     2205  CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x));
     2206  CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x);
     2207  CircleCenter.Scale(0.5);
     2208
     2209  // construct normal vector of circle
     2210  CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x);
     2211  CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x);
     2212
     2213  // calculate squared radius of circle
     2214  radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
     2215  if (radius/4. < RADIUS*RADIUS) {
     2216    CircleRadius = RADIUS*RADIUS - radius/4.;
     2217    CirclePlaneNormal.Normalize();
     2218    cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
     2219
     2220    // test whether old center is on the band's plane
     2221    if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
     2222      cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl;
     2223      OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal);
     2224    }
     2225    radius = OldSphereCenter.ScalarProduct(&OldSphereCenter);
     2226    if (fabs(radius - CircleRadius) < HULLEPSILON) {
     2227
     2228      // check SearchDirection
     2229      cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
     2230      if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {  // rotated the wrong way!
     2231        cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are not orthogonal!" << endl;
     2232      }
     2233      // get cell for the starting atom
     2234      if (LC->SetIndexToVector(&CircleCenter)) {
     2235          for(int i=0;i<NDIM;i++) // store indices of this cell
     2236          N[i] = LC->n[i];
     2237        cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
     2238      } else {
     2239        cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl;
     2240        return;
     2241      }
     2242      // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
     2243      cout << Verbose(2) << "LC Intervals:";
     2244      for (int i=0;i<NDIM;i++) {
     2245        Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
     2246        Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
     2247        cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
     2248      }
     2249      cout << endl;
     2250      for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
     2251        for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
     2252          for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
     2253            List = LC->GetCurrentCell();
     2254            //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
     2255            if (List != NULL) {
     2256              for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
     2257                Candidate = (*Runner);
     2258
     2259                // check for three unique points
     2260                if ((Candidate != BaseLine->endpoints[0]->node) && (Candidate != BaseLine->endpoints[1]->node) && (Candidate != ThirdNode)) {
     2261                  cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl;
     2262
     2263                  // construct both new centers
     2264                  GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x));
     2265                  OtherNewSphereCenter.CopyVector(&NewSphereCenter);
     2266
     2267                  if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) {
     2268                    helper.CopyVector(&NewNormalVector);
     2269                    cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl;
     2270                    radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter);
     2271                    if (radius < RADIUS*RADIUS) {
     2272                      helper.Scale(sqrt(RADIUS*RADIUS - radius));
     2273                      cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl;
     2274                      NewSphereCenter.AddVector(&helper);
     2275                      NewSphereCenter.SubtractVector(&CircleCenter);
     2276                      cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl;
     2277
     2278                      helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction
     2279                      OtherNewSphereCenter.AddVector(&helper);
     2280                      OtherNewSphereCenter.SubtractVector(&CircleCenter);
     2281                      cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl;
     2282
     2283                      // check both possible centers
     2284                      alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, NormalVector, SearchDirection);
     2285                      Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, NormalVector, SearchDirection);
     2286                      alpha = min(alpha, Otheralpha);
     2287                      if (*ShortestAngle > alpha) {
     2288                          OptCandidate = Candidate;
     2289                          *ShortestAngle = alpha;
     2290                          if (alpha != Otheralpha)
     2291                            OptCandidateCenter->CopyVector(&NewSphereCenter);
     2292                          else
     2293                            OptCandidateCenter->CopyVector(&OtherNewSphereCenter);
     2294                          cout << Verbose(1) << "ACCEPT: We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl;
     2295                      } else {
     2296                        if (OptCandidate != NULL)
     2297                          cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl;
     2298                        else
     2299                          cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl;
     2300                      }
     2301
     2302                    } else {
     2303                      cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl;
     2304                    }
     2305                  } else {
     2306                    cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl;
     2307                  }
     2308                } else {
     2309                  if (ThirdNode != NULL)
     2310                    cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " and " << *ThirdNode << " contains Candidate " << *Candidate << "." << endl;
     2311                  else
     2312                    cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " contains Candidate " << *Candidate << "." << endl;
     2313                }
     2314              }
     2315            }
     2316          }
     2317    } else {
     2318      cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
     2319    }
     2320  } else {
     2321    if (ThirdNode != NULL)
     2322      cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and third node " << *ThirdNode << " is too big!" << endl;
     2323    else
     2324      cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " is too big!" << endl;
     2325  }
     2326
     2327
     2328  cout << Verbose(1) << "End of Find_third_point_for_Tesselation" << endl;
    23592329};
     2330
     2331/** Checks whether the triangle consisting of the three atoms is already present.
     2332 * Searches for the points in Tesselation::PointsOnBoundary and checks their
     2333 * lines. If any of the three edges already has two triangles attached, false is
     2334 * returned.
     2335 * \param *out output stream for debugging
     2336 * \param *a first endpoint
     2337 * \param *b second endpoint
     2338 * \param *c third endpoint
     2339 * \return false - triangle invalid due to edge criteria, true - triangle may be added.
     2340 */
     2341bool Tesselation::CheckPresenceOfTriangle(ofstream *out, atom *a, atom *b, atom *c) {
     2342  LineMap::iterator TryAndError;
     2343  PointTestPair InsertPoint;
     2344  bool Present[3];
     2345
     2346  *out << Verbose(2) << "Begin of CheckPresenceOfTriangle" << endl;
     2347  TPS[0] = new class BoundaryPointSet(a);
     2348  TPS[1] = new class BoundaryPointSet(b);
     2349  TPS[2] = new class BoundaryPointSet(c);
     2350  for (int i=0;i<3;i++) { // check through all endpoints
     2351    InsertPoint = PointsOnBoundary.insert(PointPair(TPS[i]->node->nr, TPS[i]));
     2352    Present[i] = !InsertPoint.second;
     2353    if (Present[i]) { // if new point was not present before, increase counter
     2354      delete TPS[i];
     2355      *out << Verbose(2) << "Atom " << *((InsertPoint.first)->second->node) << " gibt's schon in der PointMap." << endl;
     2356      TPS[i] = (InsertPoint.first)->second;
     2357    }
     2358  }
     2359
     2360  // check lines
     2361  for (int i=0;i<3;i++)
     2362    if (Present[i])
     2363      for (int j=i;j<3;j++)
     2364        if (Present[j]) {
     2365          TryAndError = TPS[i]->lines.find(TPS[j]->node->nr);
     2366          if ((TryAndError != TPS[i]->lines.end()) && (TryAndError->second->TrianglesCount > 1)) {
     2367            *out << "WARNING: Line " << *TryAndError->second << " already present with " << TryAndError->second->TrianglesCount << " triangles attached." << endl;
     2368            *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;
     2369            return false;
     2370          }
     2371        }
     2372  *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;
     2373  return true;
     2374};
     2375
    23602376
    23612377/** Finds the second point of starting triangle.
     
    23702386void Find_second_point_for_Tesselation(atom* a, atom* Candidate, Vector Oben, atom*& Opt_Candidate, double Storage[3], double RADIUS, LinkedCell *LC)
    23712387{
    2372         cout << Verbose(2) << "Begin of Find_second_point_for_Tesselation" << endl;
    2373         int i;
    2374         Vector AngleCheck;
    2375         atom* Walker;
    2376         double norm = -1., angle;
    2377         LinkedAtoms *List = NULL;
    2378         int N[NDIM], Nlower[NDIM], Nupper[NDIM];
    2379 
    2380         if (LC->SetIndexToAtom(a)) {    // get cell for the starting atom
    2381                 for(int i=0;i<NDIM;i++) // store indices of this cell
    2382                         N[i] = LC->n[i];
    2383         } else {
    2384                 cerr << "ERROR: Atom " << *a << " is not found in cell " << LC->index << "." << endl;
    2385                 return;
    2386         }
    2387         // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
    2388         cout << Verbose(2) << "LC Intervals:";
    2389         for (int i=0;i<NDIM;i++) {
    2390                 Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
    2391                 Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
    2392                 cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
    2393         }
    2394         cout << endl;
    2395         for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
    2396                 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
    2397                         for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
    2398                                 List = LC->GetCurrentCell();
    2399                                 //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
    2400                                 if (List != NULL) {
    2401                                         for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
    2402                                                 Candidate = (*Runner);
    2403                                                                 // check if we only have one unique point yet ...
    2404                                                                 if (a != Candidate) {
    2405                         cout << Verbose(3) << "Current candidate is " << *Candidate << ": ";
    2406                         AngleCheck.CopyVector(&(Candidate->x));
    2407                         AngleCheck.SubtractVector(&(a->x));
    2408                         norm = AngleCheck.Norm();
    2409                                                         // second point shall have smallest angle with respect to Oben vector
    2410                                                         if (norm < RADIUS) {
    2411                                                                 angle = AngleCheck.Angle(&Oben);
    2412                                                                 if (angle < Storage[0]) {
    2413                                                                         //cout << Verbose(1) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[1]);
    2414                                                                         cout << "Is a better candidate with distance " << norm << " and " << angle << ".\n";
    2415                                                                         Opt_Candidate = Candidate;
    2416                                                                         Storage[0] = AngleCheck.Angle(&Oben);
    2417                                                                         //cout << Verbose(1) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[2]);
    2418                                                                 } else {
    2419                                                                         cout << "Looses with angle " << angle << " to a better candidate " << *Opt_Candidate << endl;
    2420                                                                 }
    2421                                                         } else {
    2422                                                                 cout << "Refused due to Radius " << norm << endl;
    2423                                                         }
    2424                                                 }
    2425                                         }
    2426                                 }
    2427                         }
    2428         cout << Verbose(2) << "End of Find_second_point_for_Tesselation" << endl;
     2388  cout << Verbose(2) << "Begin of Find_second_point_for_Tesselation" << endl;
     2389  Vector AngleCheck;
     2390  double norm = -1., angle;
     2391  LinkedAtoms *List = NULL;
     2392  int N[NDIM], Nlower[NDIM], Nupper[NDIM];
     2393
     2394  if (LC->SetIndexToAtom(a)) {  // get cell for the starting atom
     2395    for(int i=0;i<NDIM;i++) // store indices of this cell
     2396      N[i] = LC->n[i];
     2397  } else {
     2398    cerr << "ERROR: Atom " << *a << " is not found in cell " << LC->index << "." << endl;
     2399    return;
     2400  }
     2401  // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
     2402  cout << Verbose(2) << "LC Intervals:";
     2403  for (int i=0;i<NDIM;i++) {
     2404    Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
     2405    Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
     2406    cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
     2407  }
     2408  cout << endl;
     2409  for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
     2410    for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
     2411      for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
     2412        List = LC->GetCurrentCell();
     2413        //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
     2414        if (List != NULL) {
     2415          for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
     2416            Candidate = (*Runner);
     2417                // check if we only have one unique point yet ...
     2418                if (a != Candidate) {
     2419      cout << Verbose(3) << "Current candidate is " << *Candidate << ": ";
     2420      AngleCheck.CopyVector(&(Candidate->x));
     2421      AngleCheck.SubtractVector(&(a->x));
     2422      norm = AngleCheck.Norm();
     2423              // second point shall have smallest angle with respect to Oben vector
     2424              if (norm < RADIUS) {
     2425                angle = AngleCheck.Angle(&Oben);
     2426                if (angle < Storage[0]) {
     2427                  //cout << Verbose(1) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[1]);
     2428                  cout << "Is a better candidate with distance " << norm << " and " << angle << ".\n";
     2429                  Opt_Candidate = Candidate;
     2430                  Storage[0] = AngleCheck.Angle(&Oben);
     2431                  //cout << Verbose(1) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[2]);
     2432                } else {
     2433                  cout << "Looses with angle " << angle << " to a better candidate " << *Opt_Candidate << endl;
     2434                }
     2435              } else {
     2436                cout << "Refused due to Radius " << norm << endl;
     2437              }
     2438            }
     2439          }
     2440        }
     2441      }
     2442  cout << Verbose(2) << "End of Find_second_point_for_Tesselation" << endl;
    24292443};
    24302444
     
    24382452void Tesselation::Find_starting_triangle(ofstream *out, molecule *mol, const double RADIUS, LinkedCell *LC)
    24392453{
    2440         cout << Verbose(1) << "Begin of Find_starting_triangle\n";
    2441         int i = 0;
    2442         LinkedAtoms *List = NULL;
    2443         atom* Walker;
    2444         atom* FirstPoint;
    2445         atom* SecondPoint;
    2446         atom* MaxAtom[NDIM];
    2447         double max_coordinate[NDIM];
    2448         Vector Oben;
    2449         Vector helper;
    2450         Vector Chord;
    2451         Vector SearchDirection;
    2452         Vector OptCandidateCenter;
    2453 
    2454         Oben.Zero();
    2455 
    2456         for (i = 0; i < 3; i++) {
    2457                 MaxAtom[i] = NULL;
    2458                 max_coordinate[i] = -1;
    2459         }
    2460 
    2461         // 1. searching topmost atom with respect to each axis
    2462         for (int i=0;i<NDIM;i++) { // each axis
    2463                 LC->n[i] = LC->N[i]-1; // current axis is topmost cell
    2464                 for (LC->n[(i+1)%NDIM]=0;LC->n[(i+1)%NDIM]<LC->N[(i+1)%NDIM];LC->n[(i+1)%NDIM]++)
    2465                         for (LC->n[(i+2)%NDIM]=0;LC->n[(i+2)%NDIM]<LC->N[(i+2)%NDIM];LC->n[(i+2)%NDIM]++) {
    2466                                 List = LC->GetCurrentCell();
    2467                                 //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
    2468                                 if (List != NULL) {
    2469                                         for (LinkedAtoms::iterator Runner = List->begin();Runner != List->end();Runner++) {
    2470                                                 cout << Verbose(2) << "Current atom is " << *(*Runner) << "." << endl;
    2471                                                 if ((*Runner)->x.x[i] > max_coordinate[i]) {
    2472                                                         max_coordinate[i] = (*Runner)->x.x[i];
    2473                                                         MaxAtom[i] = (*Runner);
    2474                                                 }
    2475                                         }
    2476                                 } else {
    2477                                         cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << " is invalid!" << endl;
    2478                                 }
    2479                         }
    2480         }
    2481 
    2482         cout << Verbose(2) << "Found maximum coordinates: ";
    2483         for (int i=0;i<NDIM;i++)
    2484                 cout << i << ": " << *MaxAtom[i] << "\t";
    2485         cout << endl;
    2486         const int k = 1;                // arbitrary choice
    2487         Oben.x[k] = 1.;
    2488         FirstPoint = MaxAtom[k];
    2489         cout << Verbose(1) << "Coordinates of start atom " << *FirstPoint << " at " << FirstPoint->x << "." << endl;
    2490 
    2491         // add first point
    2492         AddTrianglePoint(FirstPoint, 0);
    2493 
    2494         double ShortestAngle;
    2495         atom* Opt_Candidate = NULL;
    2496         ShortestAngle = 999999.; // This will contain the angle, which will be always positive (when looking for second point), when looking for third point this will be the quadrant.
    2497 
    2498         Find_second_point_for_Tesselation(FirstPoint, NULL, Oben, Opt_Candidate, &ShortestAngle, RADIUS, LC); // we give same point as next candidate as its bonds are looked into in find_second_...
    2499         SecondPoint = Opt_Candidate;
    2500         cout << Verbose(1) << "Found second point is " << *SecondPoint << " at " << SecondPoint->x << ".\n";
    2501 
    2502         // add second point and first baseline
    2503         AddTrianglePoint(SecondPoint, 1);
    2504         AddTriangleLine(TPS[0], TPS[1], 0);
    2505 
    2506         helper.CopyVector(&(FirstPoint->x));
    2507         helper.SubtractVector(&(SecondPoint->x));
    2508         helper.Normalize();
    2509         Oben.ProjectOntoPlane(&helper);
    2510         Oben.Normalize();
    2511         helper.VectorProduct(&Oben);
    2512         ShortestAngle = 2.*M_PI; // This will indicate the quadrant.
    2513 
    2514         Chord.CopyVector(&(FirstPoint->x)); // bring into calling function
    2515         Chord.SubtractVector(&(SecondPoint->x));
    2516         double radius = Chord.ScalarProduct(&Chord);
    2517         double CircleRadius = sqrt(RADIUS*RADIUS - radius/4.);
    2518         helper.CopyVector(&Oben);
    2519         helper.Scale(CircleRadius);
    2520         // Now, oben and helper are two orthonormalized vectors in the plane defined by Chord (not normalized)
    2521 
    2522         cout << Verbose(2) << "Looking for third point candidates \n";
    2523         // look in one direction of baseline for initial candidate
    2524         Opt_Candidate = NULL;
    2525         SearchDirection.MakeNormalVector(&Chord, &Oben);        // whether we look "left" first or "right" first is not important ...
    2526 
    2527         cout << Verbose(1) << "Looking for third point candidates ...\n";
    2528         Find_third_point_for_Tesselation(Oben, SearchDirection, helper, BLS[0], NULL, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC);
    2529         cout << Verbose(1) << "Third Point is " << *Opt_Candidate << endl;
    2530 
    2531         // add third point
    2532         AddTrianglePoint(Opt_Candidate, 2);
    2533 
    2534         // FOUND Starting Triangle: FirstPoint, SecondPoint, Opt_Candidate
    2535 
    2536         // Finally, we only have to add the found further lines
    2537         AddTriangleLine(TPS[1], TPS[2], 1);
    2538         AddTriangleLine(TPS[0], TPS[2], 2);
    2539         // ... and triangles to the Maps of the Tesselation class
    2540         BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    2541         AddTriangleToLines();
    2542         // ... and calculate its normal vector (with correct orientation)
    2543         OptCandidateCenter.Scale(-1.);
    2544         cout << Verbose(2) << "Oben is currently " << OptCandidateCenter << "." << endl;
    2545         BTS->GetNormalVector(OptCandidateCenter);
    2546         cout << Verbose(0) << "==> The found starting triangle consists of " << *FirstPoint << ", " << *SecondPoint << " and " << *Opt_Candidate << " with normal vector " << BTS->NormalVector << ".\n";
    2547         cout << Verbose(2) << "Projection is " << BTS->NormalVector.Projection(&Oben) << "." << endl;
    2548         cout << Verbose(1) << "End of Find_starting_triangle\n";
     2454  cout << Verbose(1) << "Begin of Find_starting_triangle\n";
     2455  int i = 0;
     2456  LinkedAtoms *List = NULL;
     2457  atom* FirstPoint;
     2458  atom* SecondPoint;
     2459  atom* MaxAtom[NDIM];
     2460  double max_coordinate[NDIM];
     2461  Vector Oben;
     2462  Vector helper;
     2463  Vector Chord;
     2464  Vector SearchDirection;
     2465  Vector OptCandidateCenter;
     2466
     2467  Oben.Zero();
     2468
     2469  for (i = 0; i < 3; i++) {
     2470    MaxAtom[i] = NULL;
     2471    max_coordinate[i] = -1;
     2472  }
     2473
     2474  // 1. searching topmost atom with respect to each axis
     2475  for (int i=0;i<NDIM;i++) { // each axis
     2476    LC->n[i] = LC->N[i]-1; // current axis is topmost cell
     2477    for (LC->n[(i+1)%NDIM]=0;LC->n[(i+1)%NDIM]<LC->N[(i+1)%NDIM];LC->n[(i+1)%NDIM]++)
     2478      for (LC->n[(i+2)%NDIM]=0;LC->n[(i+2)%NDIM]<LC->N[(i+2)%NDIM];LC->n[(i+2)%NDIM]++) {
     2479        List = LC->GetCurrentCell();
     2480        //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
     2481        if (List != NULL) {
     2482          for (LinkedAtoms::iterator Runner = List->begin();Runner != List->end();Runner++) {
     2483            cout << Verbose(2) << "Current atom is " << *(*Runner) << "." << endl;
     2484            if ((*Runner)->x.x[i] > max_coordinate[i]) {
     2485              max_coordinate[i] = (*Runner)->x.x[i];
     2486              MaxAtom[i] = (*Runner);
     2487            }
     2488          }
     2489        } else {
     2490          cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << " is invalid!" << endl;
     2491        }
     2492      }
     2493  }
     2494
     2495  cout << Verbose(2) << "Found maximum coordinates: ";
     2496  for (int i=0;i<NDIM;i++)
     2497    cout << i << ": " << *MaxAtom[i] << "\t";
     2498  cout << endl;
     2499  const int k = 1;    // arbitrary choice
     2500  Oben.x[k] = 1.;
     2501  FirstPoint = MaxAtom[k];
     2502  cout << Verbose(1) << "Coordinates of start atom " << *FirstPoint << " at " << FirstPoint->x << "." << endl;
     2503
     2504  // add first point
     2505  AddTrianglePoint(FirstPoint, 0);
     2506
     2507  double ShortestAngle;
     2508  atom* Opt_Candidate = NULL;
     2509  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.
     2510
     2511  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_...
     2512  SecondPoint = Opt_Candidate;
     2513  cout << Verbose(1) << "Found second point is " << *SecondPoint << " at " << SecondPoint->x << ".\n";
     2514
     2515  // add second point and first baseline
     2516  AddTrianglePoint(SecondPoint, 1);
     2517  AddTriangleLine(TPS[0], TPS[1], 0);
     2518
     2519  helper.CopyVector(&(FirstPoint->x));
     2520  helper.SubtractVector(&(SecondPoint->x));
     2521  helper.Normalize();
     2522  Oben.ProjectOntoPlane(&helper);
     2523  Oben.Normalize();
     2524  helper.VectorProduct(&Oben);
     2525  ShortestAngle = 2.*M_PI; // This will indicate the quadrant.
     2526
     2527  Chord.CopyVector(&(FirstPoint->x)); // bring into calling function
     2528  Chord.SubtractVector(&(SecondPoint->x));
     2529  double radius = Chord.ScalarProduct(&Chord);
     2530  double CircleRadius = sqrt(RADIUS*RADIUS - radius/4.);
     2531  helper.CopyVector(&Oben);
     2532  helper.Scale(CircleRadius);
     2533  // Now, oben and helper are two orthonormalized vectors in the plane defined by Chord (not normalized)
     2534
     2535  cout << Verbose(2) << "Looking for third point candidates \n";
     2536  // look in one direction of baseline for initial candidate
     2537  Opt_Candidate = NULL;
     2538  SearchDirection.MakeNormalVector(&Chord, &Oben);  // whether we look "left" first or "right" first is not important ...
     2539
     2540  cout << Verbose(1) << "Looking for third point candidates ...\n";
     2541  Find_third_point_for_Tesselation(Oben, SearchDirection, helper, BLS[0], NULL, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC);
     2542  cout << Verbose(1) << "Third Point is " << *Opt_Candidate << endl;
     2543
     2544  // add third point
     2545  AddTrianglePoint(Opt_Candidate, 2);
     2546
     2547  // FOUND Starting Triangle: FirstPoint, SecondPoint, Opt_Candidate
     2548
     2549  // Finally, we only have to add the found further lines
     2550  AddTriangleLine(TPS[1], TPS[2], 1);
     2551  AddTriangleLine(TPS[0], TPS[2], 2);
     2552  // ... and triangles to the Maps of the Tesselation class
     2553  BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     2554  AddTriangleToLines();
     2555  // ... and calculate its normal vector (with correct orientation)
     2556  OptCandidateCenter.Scale(-1.);
     2557  cout << Verbose(2) << "Oben is currently " << OptCandidateCenter << "." << endl;
     2558  BTS->GetNormalVector(OptCandidateCenter);
     2559  cout << Verbose(0) << "==> The found starting triangle consists of " << *FirstPoint << ", " << *SecondPoint << " and " << *Opt_Candidate << " with normal vector " << BTS->NormalVector << ".\n";
     2560  cout << Verbose(2) << "Projection is " << BTS->NormalVector.Projection(&Oben) << "." << endl;
     2561  cout << Verbose(1) << "End of Find_starting_triangle\n";
    25492562};
    25502563
     
    25602573 */
    25612574bool Tesselation::Find_next_suitable_triangle(ofstream *out,
    2562                 molecule *mol, BoundaryLineSet &Line, BoundaryTriangleSet &T,
    2563                 const double& RADIUS, int N, const char *tempbasename, LinkedCell *LC)
    2564 {
    2565         cout << Verbose(1) << "Begin of Find_next_suitable_triangle\n";
    2566         ofstream *tempstream = NULL;
    2567         char NumberName[255];
    2568         double tmp;
    2569 
    2570         atom* Opt_Candidate = NULL;
    2571         Vector OptCandidateCenter;
    2572 
    2573         Vector CircleCenter;
    2574         Vector CirclePlaneNormal;
    2575         Vector OldSphereCenter;
    2576         Vector SearchDirection;
    2577         Vector helper;
    2578         atom *ThirdNode = NULL;
    2579         double ShortestAngle = 2.*M_PI; // This will indicate the quadrant.
    2580         double radius, CircleRadius;
    2581 
    2582         cout << Verbose(1) << "Current baseline is " << Line << " of triangle " << T << "." << endl;
    2583         for (int i=0;i<3;i++)
    2584                 if ((T.endpoints[i]->node != Line.endpoints[0]->node) && (T.endpoints[i]->node != Line.endpoints[1]->node))
    2585                         ThirdNode = T.endpoints[i]->node;
    2586 
    2587         // construct center of circle
    2588         CircleCenter.CopyVector(&Line.endpoints[0]->node->x);
    2589         CircleCenter.AddVector(&Line.endpoints[1]->node->x);
    2590         CircleCenter.Scale(0.5);
    2591 
    2592         // construct normal vector of circle
    2593         CirclePlaneNormal.CopyVector(&Line.endpoints[0]->node->x);
    2594         CirclePlaneNormal.SubtractVector(&Line.endpoints[1]->node->x);
    2595 
    2596         // calculate squared radius of circle
    2597         radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
    2598         if (radius/4. < RADIUS*RADIUS) {
    2599                 CircleRadius = RADIUS*RADIUS - radius/4.;
    2600                 CirclePlaneNormal.Normalize();
    2601                 cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
    2602 
    2603                 // construct old center
    2604                 GetCenterofCircumcircle(&OldSphereCenter, &(T.endpoints[0]->node->x), &(T.endpoints[1]->node->x), &(T.endpoints[2]->node->x));
    2605                 helper.CopyVector(&T.NormalVector);     // normal vector ensures that this is correct center of the two possible ones
    2606                 radius = Line.endpoints[0]->node->x.DistanceSquared(&OldSphereCenter);
    2607                 helper.Scale(sqrt(RADIUS*RADIUS - radius));
    2608                 OldSphereCenter.AddVector(&helper);
    2609                 OldSphereCenter.SubtractVector(&CircleCenter);
    2610                 cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;
    2611 
    2612                 // construct SearchDirection
    2613                 SearchDirection.MakeNormalVector(&T.NormalVector, &CirclePlaneNormal);
    2614                 helper.CopyVector(&Line.endpoints[0]->node->x);
    2615                 helper.SubtractVector(&ThirdNode->x);
    2616                 if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)      // ohoh, SearchDirection points inwards!
    2617                         SearchDirection.Scale(-1.);
    2618                 SearchDirection.ProjectOntoPlane(&OldSphereCenter);
    2619                 SearchDirection.Normalize();
    2620                 cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
    2621                 if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {      // rotated the wrong way!
    2622                         cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl;
    2623                 }
    2624 
    2625                 // add third point
    2626                 cout << Verbose(1) << "Looking for third point candidates for triangle ... " << endl;
    2627                 Find_third_point_for_Tesselation(T.NormalVector, SearchDirection, OldSphereCenter, &Line, ThirdNode, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC);
    2628 
    2629         } else {
    2630                 cout << Verbose(1) << "Circumcircle for base line " << Line << " and base triangle " << T << " is too big!" << endl;
    2631         }
    2632 
    2633         if (Opt_Candidate == NULL) {
    2634                 cerr << "WARNING: Could not find a suitable candidate." << endl;
    2635                 return false;
    2636         }
    2637         cout << Verbose(1) << " Optimal candidate is " << *Opt_Candidate << " with circumsphere's center at " << OptCandidateCenter << "." << endl;
    2638 
    2639         // check whether all edges of the new triangle still have space for one more triangle (i.e. TriangleCount <2)
    2640         atom *AtomCandidates[3];
    2641         AtomCandidates[0] = Opt_Candidate;
    2642         AtomCandidates[1] = Line.endpoints[0]->node;
    2643         AtomCandidates[2] = Line.endpoints[1]->node;
    2644         bool flag = CheckPresenceOfTriangle(out, AtomCandidates);
    2645 
    2646         if (flag) { // if so, add
    2647                 AddTrianglePoint(Opt_Candidate, 0);
    2648                 AddTrianglePoint(Line.endpoints[0]->node, 1);
    2649                 AddTrianglePoint(Line.endpoints[1]->node, 2);
    2650 
    2651                 AddTriangleLine(TPS[0], TPS[1], 0);
    2652                 AddTriangleLine(TPS[0], TPS[2], 1);
    2653                 AddTriangleLine(TPS[1], TPS[2], 2);
    2654 
    2655                 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    2656                 AddTriangleToLines();
    2657 
    2658                 OptCandidateCenter.Scale(-1.);
    2659                 BTS->GetNormalVector(OptCandidateCenter);
    2660                 OptCandidateCenter.Scale(-1.);
    2661 
    2662                 cout << "--> New triangle with " << *BTS << " and normal vector " << BTS->NormalVector << " for this triangle ... " << endl;
    2663                 cout << Verbose(1) << "We have "<< TrianglesOnBoundaryCount << " for line " << Line << "." << endl;
    2664         } else { // else, yell and do nothing
    2665                 cout << Verbose(1) << "This triangle consisting of ";
    2666                 cout << *Opt_Candidate << ", ";
    2667                 cout << *Line.endpoints[0]->node << " and ";
    2668                 cout << *Line.endpoints[1]->node << " ";
    2669                 cout << "is invalid!" << endl;
    2670                 return false;
    2671         }
    2672 
    2673         if (flag && (DoSingleStepOutput && (TrianglesOnBoundaryCount % 10 == 0))) { // if we have a new triangle and want to output each new triangle configuration
    2674                 sprintf(NumberName, "-%04d-%s_%s_%s", TriangleFilesWritten, BTS->endpoints[0]->node->Name, BTS->endpoints[1]->node->Name, BTS->endpoints[2]->node->Name);
    2675                 if (DoTecplotOutput) {
    2676                         string NameofTempFile(tempbasename);
    2677                         NameofTempFile.append(NumberName);
    2678                         for(size_t npos = NameofTempFile.find_first_of(' '); npos != -1; npos = NameofTempFile.find(' ', npos))
    2679                                 NameofTempFile.erase(npos, 1);
    2680                         NameofTempFile.append(TecplotSuffix);
    2681                         cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
    2682                         tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
    2683                         write_tecplot_file(out, tempstream, this, mol, TriangleFilesWritten);
    2684                         tempstream->close();
    2685                         tempstream->flush();
    2686                         delete(tempstream);
    2687                 }
    2688 
    2689                 if (DoRaster3DOutput) {
    2690                         string NameofTempFile(tempbasename);
    2691                         NameofTempFile.append(NumberName);
    2692                         for(size_t npos = NameofTempFile.find_first_of(' '); npos != -1; npos = NameofTempFile.find(' ', npos))
    2693                                 NameofTempFile.erase(npos, 1);
    2694                         NameofTempFile.append(Raster3DSuffix);
    2695                         cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
    2696                         tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
    2697                         write_raster3d_file(out, tempstream, this, mol);
    2698                         // include the current position of the virtual sphere in the temporary raster3d file
    2699                         // make the circumsphere's center absolute again
    2700                         helper.CopyVector(&Line.endpoints[0]->node->x);
    2701                         helper.AddVector(&Line.endpoints[1]->node->x);
    2702                         helper.Scale(0.5);
    2703                         OptCandidateCenter.AddVector(&helper);
    2704                         Vector *center = mol->DetermineCenterOfAll(out);
    2705                         OptCandidateCenter.AddVector(center);
    2706                         delete(center);
    2707                         // and add to file plus translucency object
    2708                         *tempstream << "# current virtual sphere\n";
    2709                         *tempstream << "8\n     25.0            0.6              -1.0 -1.0 -1.0          0.2                            0 0 0 0\n";
    2710                         *tempstream << "2\n     " << OptCandidateCenter.x[0] << " " << OptCandidateCenter.x[1] << " " << OptCandidateCenter.x[2] << "\t" << RADIUS << "\t1 0 0\n";
    2711                         *tempstream << "9\n     terminating special property\n";
    2712                         tempstream->close();
    2713                         tempstream->flush();
    2714                         delete(tempstream);
    2715                 }
    2716                 if (DoTecplotOutput || DoRaster3DOutput)
    2717                         TriangleFilesWritten++;
    2718         }
    2719 
    2720         cout << Verbose(1) << "End of Find_next_suitable_triangle\n";
    2721         return true;
     2575    molecule *mol, BoundaryLineSet &Line, BoundaryTriangleSet &T,
     2576    const double& RADIUS, int N, const char *tempbasename, LinkedCell *LC)
     2577{
     2578  cout << Verbose(1) << "Begin of Find_next_suitable_triangle\n";
     2579  ofstream *tempstream = NULL;
     2580  char NumberName[255];
     2581
     2582  atom* Opt_Candidate = NULL;
     2583  Vector OptCandidateCenter;
     2584
     2585  Vector CircleCenter;
     2586  Vector CirclePlaneNormal;
     2587  Vector OldSphereCenter;
     2588  Vector SearchDirection;
     2589  Vector helper;
     2590  atom *ThirdNode = NULL;
     2591  double ShortestAngle = 2.*M_PI; // This will indicate the quadrant.
     2592  double radius, CircleRadius;
     2593
     2594  cout << Verbose(1) << "Current baseline is " << Line << " of triangle " << T << "." << endl;
     2595  for (int i=0;i<3;i++)
     2596    if ((T.endpoints[i]->node != Line.endpoints[0]->node) && (T.endpoints[i]->node != Line.endpoints[1]->node))
     2597      ThirdNode = T.endpoints[i]->node;
     2598
     2599  // construct center of circle
     2600  CircleCenter.CopyVector(&Line.endpoints[0]->node->x);
     2601  CircleCenter.AddVector(&Line.endpoints[1]->node->x);
     2602  CircleCenter.Scale(0.5);
     2603
     2604  // construct normal vector of circle
     2605  CirclePlaneNormal.CopyVector(&Line.endpoints[0]->node->x);
     2606  CirclePlaneNormal.SubtractVector(&Line.endpoints[1]->node->x);
     2607
     2608  // calculate squared radius of circle
     2609  radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
     2610  if (radius/4. < RADIUS*RADIUS) {
     2611    CircleRadius = RADIUS*RADIUS - radius/4.;
     2612    CirclePlaneNormal.Normalize();
     2613    cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
     2614
     2615    // construct old center
     2616    GetCenterofCircumcircle(&OldSphereCenter, &(T.endpoints[0]->node->x), &(T.endpoints[1]->node->x), &(T.endpoints[2]->node->x));
     2617    helper.CopyVector(&T.NormalVector);  // normal vector ensures that this is correct center of the two possible ones
     2618    radius = Line.endpoints[0]->node->x.DistanceSquared(&OldSphereCenter);
     2619    helper.Scale(sqrt(RADIUS*RADIUS - radius));
     2620    OldSphereCenter.AddVector(&helper);
     2621    OldSphereCenter.SubtractVector(&CircleCenter);
     2622    cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;
     2623
     2624    // construct SearchDirection
     2625    SearchDirection.MakeNormalVector(&T.NormalVector, &CirclePlaneNormal);
     2626    helper.CopyVector(&Line.endpoints[0]->node->x);
     2627    helper.SubtractVector(&ThirdNode->x);
     2628    if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)  // ohoh, SearchDirection points inwards!
     2629      SearchDirection.Scale(-1.);
     2630    SearchDirection.ProjectOntoPlane(&OldSphereCenter);
     2631    SearchDirection.Normalize();
     2632    cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
     2633    if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {  // rotated the wrong way!
     2634      cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl;
     2635    }
     2636
     2637    // add third point
     2638    cout << Verbose(1) << "Looking for third point candidates for triangle ... " << endl;
     2639    Find_third_point_for_Tesselation(T.NormalVector, SearchDirection, OldSphereCenter, &Line, ThirdNode, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC);
     2640
     2641  } else {
     2642    cout << Verbose(1) << "Circumcircle for base line " << Line << " and base triangle " << T << " is too big!" << endl;
     2643  }
     2644
     2645  if (Opt_Candidate == NULL) {
     2646    cerr << "WARNING: Could not find a suitable candidate." << endl;
     2647    return false;
     2648  }
     2649  cout << Verbose(1) << " Optimal candidate is " << *Opt_Candidate << " with circumsphere's center at " << OptCandidateCenter << "." << endl;
     2650
     2651  // check whether all edges of the new triangle still have space for one more triangle (i.e. TriangleCount <2)
     2652  bool flag = CheckPresenceOfTriangle(out, Opt_Candidate, Line.endpoints[0]->node, Line.endpoints[1]->node);
     2653
     2654  if (flag) { // if so, add
     2655    AddTrianglePoint(Opt_Candidate, 0);
     2656    AddTrianglePoint(Line.endpoints[0]->node, 1);
     2657    AddTrianglePoint(Line.endpoints[1]->node, 2);
     2658
     2659    AddTriangleLine(TPS[0], TPS[1], 0);
     2660    AddTriangleLine(TPS[0], TPS[2], 1);
     2661    AddTriangleLine(TPS[1], TPS[2], 2);
     2662
     2663    BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     2664    AddTriangleToLines();
     2665
     2666    OptCandidateCenter.Scale(-1.);
     2667    BTS->GetNormalVector(OptCandidateCenter);
     2668    OptCandidateCenter.Scale(-1.);
     2669
     2670    cout << "--> New triangle with " << *BTS << " and normal vector " << BTS->NormalVector << " for this triangle ... " << endl;
     2671    cout << Verbose(1) << "We have "<< TrianglesOnBoundaryCount << " for line " << Line << "." << endl;
     2672  } else { // else, yell and do nothing
     2673    cout << Verbose(1) << "This triangle consisting of ";
     2674    cout << *Opt_Candidate << ", ";
     2675    cout << *Line.endpoints[0]->node << " and ";
     2676    cout << *Line.endpoints[1]->node << " ";
     2677    cout << "is invalid!" << endl;
     2678    return false;
     2679  }
     2680
     2681  if (flag && (DoSingleStepOutput && (TrianglesOnBoundaryCount % 10 == 0))) { // if we have a new triangle and want to output each new triangle configuration
     2682    sprintf(NumberName, "-%04d-%s_%s_%s", TriangleFilesWritten, BTS->endpoints[0]->node->Name, BTS->endpoints[1]->node->Name, BTS->endpoints[2]->node->Name);
     2683    if (DoTecplotOutput) {
     2684      string NameofTempFile(tempbasename);
     2685      NameofTempFile.append(NumberName);
     2686      for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
     2687        NameofTempFile.erase(npos, 1);
     2688      NameofTempFile.append(TecplotSuffix);
     2689      cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
     2690      tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
     2691      write_tecplot_file(out, tempstream, this, mol, TriangleFilesWritten);
     2692      tempstream->close();
     2693      tempstream->flush();
     2694      delete(tempstream);
     2695    }
     2696
     2697    if (DoRaster3DOutput) {
     2698      string NameofTempFile(tempbasename);
     2699      NameofTempFile.append(NumberName);
     2700      for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
     2701        NameofTempFile.erase(npos, 1);
     2702      NameofTempFile.append(Raster3DSuffix);
     2703      cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
     2704      tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
     2705      write_raster3d_file(out, tempstream, this, mol);
     2706      // include the current position of the virtual sphere in the temporary raster3d file
     2707      // make the circumsphere's center absolute again
     2708      helper.CopyVector(&Line.endpoints[0]->node->x);
     2709      helper.AddVector(&Line.endpoints[1]->node->x);
     2710      helper.Scale(0.5);
     2711      OptCandidateCenter.AddVector(&helper);
     2712      Vector *center = mol->DetermineCenterOfAll(out);
     2713      OptCandidateCenter.AddVector(center);
     2714      delete(center);
     2715      // and add to file plus translucency object
     2716      *tempstream << "# current virtual sphere\n";
     2717      *tempstream << "8\n  25.0    0.6     -1.0 -1.0 -1.0     0.2        0 0 0 0\n";
     2718      *tempstream << "2\n  " << OptCandidateCenter.x[0] << " " << OptCandidateCenter.x[1] << " " << OptCandidateCenter.x[2] << "\t" << RADIUS << "\t1 0 0\n";
     2719      *tempstream << "9\n  terminating special property\n";
     2720      tempstream->close();
     2721      tempstream->flush();
     2722      delete(tempstream);
     2723    }
     2724    if (DoTecplotOutput || DoRaster3DOutput)
     2725      TriangleFilesWritten++;
     2726  }
     2727
     2728  cout << Verbose(1) << "End of Find_next_suitable_triangle\n";
     2729  return true;
    27222730};
    27232731
     
    27322740void Find_non_convex_border(ofstream *out, molecule* mol, class Tesselation *Tess, class LinkedCell *LCList, const char *filename, const double RADIUS)
    27332741{
    2734         int N = 0;
    2735         bool freeTess = false;
    2736         *out << Verbose(1) << "Entering search for non convex hull. " << endl;
    2737         if (Tess == NULL) {
    2738                 *out << Verbose(1) << "Allocating Tesselation struct ..." << endl;
    2739                 Tess = new Tesselation;
    2740                 freeTess = true;
    2741         }
    2742         bool freeLC = false;
    2743         LineMap::iterator baseline;
    2744         *out << Verbose(0) << "Begin of Find_non_convex_border\n";
    2745         bool flag = false;      // marks whether we went once through all baselines without finding any without two triangles
    2746         bool failflag = false;
    2747 
    2748         if (LCList == NULL) {
    2749                 LCList = new LinkedCell(mol, 2.*RADIUS);
    2750                 freeLC = true;
    2751         }
    2752 
    2753         Tess->Find_starting_triangle(out, mol, RADIUS, LCList);
    2754 
    2755         baseline = Tess->LinesOnBoundary.begin();
    2756         while ((baseline != Tess->LinesOnBoundary.end()) || (flag)) {
    2757                 if (baseline->second->TrianglesCount == 1) {
    2758                         failflag = Tess->Find_next_suitable_triangle(out, mol, *(baseline->second), *(((baseline->second->triangles.begin()))->second), RADIUS, N, filename, LCList); //the line is there, so there is a triangle, but only one.
    2759                         flag = flag || failflag;
    2760                         if (!failflag)
    2761                                 cerr << "WARNING: Find_next_suitable_triangle failed." << endl;
    2762                 } else {
    2763                         cout << Verbose(1) << "Line " << *baseline->second << " has " << baseline->second->TrianglesCount << " triangles adjacent" << endl;
    2764                 }
    2765                 N++;
    2766                 baseline++;
    2767                 if ((baseline == Tess->LinesOnBoundary.end()) && (flag)) {
    2768                         baseline = Tess->LinesOnBoundary.begin();        // restart if we reach end due to newly inserted lines
    2769                         flag = false;
    2770                 }
    2771         }
    2772         if (1) { //failflag) {
    2773                 *out << Verbose(1) << "Writing final tecplot file\n";
    2774                 if (DoTecplotOutput) {
    2775                         string OutputName(filename);
    2776                         OutputName.append(TecplotSuffix);
    2777                         ofstream *tecplot = new ofstream(OutputName.c_str());
    2778                         write_tecplot_file(out, tecplot, Tess, mol, -1);
    2779                         tecplot->close();
    2780                         delete(tecplot);
    2781                 }
    2782                 if (DoRaster3DOutput) {
    2783                         string OutputName(filename);
    2784                         OutputName.append(Raster3DSuffix);
    2785                         ofstream *raster = new ofstream(OutputName.c_str());
    2786                         write_raster3d_file(out, raster, Tess, mol);
    2787                         raster->close();
    2788                         delete(raster);
    2789                 }
    2790         } else {
    2791                 cerr << "ERROR: Could definately not find all necessary triangles!" << endl;
    2792         }
    2793         if (freeTess)
    2794                 delete(Tess);
    2795         if (freeLC)
    2796                 delete(LCList);
    2797         *out << Verbose(0) << "End of Find_non_convex_border\n";
     2742  int N = 0;
     2743  bool freeTess = false;
     2744  *out << Verbose(1) << "Entering search for non convex hull. " << endl;
     2745  if (Tess == NULL) {
     2746    *out << Verbose(1) << "Allocating Tesselation struct ..." << endl;
     2747    Tess = new Tesselation;
     2748    freeTess = true;
     2749  }
     2750  bool freeLC = false;
     2751  LineMap::iterator baseline;
     2752  *out << Verbose(0) << "Begin of Find_non_convex_border\n";
     2753  bool flag = false;  // marks whether we went once through all baselines without finding any without two triangles
     2754  bool failflag = false;
     2755
     2756  if (LCList == NULL) {
     2757    LCList = new LinkedCell(mol, 2.*RADIUS);
     2758    freeLC = true;
     2759  }
     2760
     2761  Tess->Find_starting_triangle(out, mol, RADIUS, LCList);
     2762
     2763  baseline = Tess->LinesOnBoundary.begin();
     2764  while ((baseline != Tess->LinesOnBoundary.end()) || (flag)) {
     2765    if (baseline->second->TrianglesCount == 1) {
     2766      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.
     2767      flag = flag || failflag;
     2768      if (!failflag)
     2769        cerr << "WARNING: Find_next_suitable_triangle failed." << endl;
     2770    } else {
     2771      cout << Verbose(1) << "Line " << *baseline->second << " has " << baseline->second->TrianglesCount << " triangles adjacent" << endl;
     2772    }
     2773    N++;
     2774    baseline++;
     2775    if ((baseline == Tess->LinesOnBoundary.end()) && (flag)) {
     2776      baseline = Tess->LinesOnBoundary.begin();  // restart if we reach end due to newly inserted lines
     2777      flag = false;
     2778    }
     2779  }
     2780  if (1) { //failflag) {
     2781    *out << Verbose(1) << "Writing final tecplot file\n";
     2782    if (DoTecplotOutput) {
     2783      string OutputName(filename);
     2784      OutputName.append(TecplotSuffix);
     2785      ofstream *tecplot = new ofstream(OutputName.c_str());
     2786      write_tecplot_file(out, tecplot, Tess, mol, -1);
     2787      tecplot->close();
     2788      delete(tecplot);
     2789    }
     2790    if (DoRaster3DOutput) {
     2791      string OutputName(filename);
     2792      OutputName.append(Raster3DSuffix);
     2793      ofstream *raster = new ofstream(OutputName.c_str());
     2794      write_raster3d_file(out, raster, Tess, mol);
     2795      raster->close();
     2796      delete(raster);
     2797    }
     2798  } else {
     2799    cerr << "ERROR: Could definately not find all necessary triangles!" << endl;
     2800  }
     2801  if (freeTess)
     2802    delete(Tess);
     2803  if (freeLC)
     2804    delete(LCList);
     2805  *out << Verbose(0) << "End of Find_non_convex_border\n";
    27982806};
    27992807
  • src/boundary.hpp

    r375b458 r51c910  
    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 *a, atom *b, atom *c);
     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
     
    120120void Find_next_suitable_point(class BoundaryTriangleSet *BaseTriangle, class BoundaryLineSet *BaseLine, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC);
    121121
    122 
    123122#endif /*BOUNDARY_HPP_*/
  • src/builder.cpp

    r375b458 r51c910  
    282282    case 'a':
    283283      cout << Verbose(0) << "Centering atoms in config file on origin." << endl;
    284       mol->CenterOrigin((ofstream *)&cout, &x);
     284      mol->CenterOrigin((ofstream *)&cout);
    285285      break;
    286286    case 'b':
    287287      cout << Verbose(0) << "Centering atoms in config file on center of gravity." << endl;
    288       mol->CenterGravity((ofstream *)&cout, &x);
     288      mol->CenterPeriodic((ofstream *)&cout);
    289289      break;
    290290    case 'c':
     
    295295      }
    296296      mol->CenterEdge((ofstream *)&cout, &x);  // make every coordinate positive
    297       mol->Translate(&y); // translate by boundary
     297      mol->Center.AddVector(&y); // translate by boundary
    298298      helper.CopyVector(&y);
    299299      helper.Scale(2.);
     
    436436static void RemoveAtoms(molecule *mol)
    437437{
    438   atom *first, *second, *third;
     438  atom *first, *second;
    439439  int axis;
    440440  double tmp1, tmp2;
     
    459459      break;
    460460    case 'b':
    461       third = mol->AskAtom("Enter number of atom as reference point: ");
     461      second = mol->AskAtom("Enter number of atom as reference point: ");
    462462      cout << Verbose(0) << "Enter radius: ";
    463463      cin >> tmp1;
     
    467467        first = second;
    468468        second = first->next;
    469         if (first->x.DistanceSquared((const Vector *)&third->x) > tmp1*tmp1) // distance to first above radius ...
     469        if (first->x.DistanceSquared((const Vector *)&second->x) > tmp1*tmp1) // distance to first above radius ...
    470470          mol->RemoveAtom(first);
    471471      }
     
    634634static void ManipulateAtoms(periodentafel *periode, MoleculeListClass *molecules, config *configuration)
    635635{
    636   atom *first, *second, *third, *fourth;
    637   Vector **atoms;
     636  atom *first, *second;
    638637  molecule *mol = NULL;
    639638  Vector x,y,z,n; // coordinates for absolute point in cell volume
    640639  double *factor; // unit factor if desired
    641   double a,b,c;
    642640  double bond, min_bond;
    643641  char choice;  // menu choice char
     
    652650  cout << Verbose(0) << "all else - go back" << endl;
    653651  cout << Verbose(0) << "===============================================" << endl;
    654   if (molecules->NumberOfActiveMolecules() > 0)
     652  if (molecules->NumberOfActiveMolecules() > 1)
    655653    cout << Verbose(0) << "WARNING: There is more than one molecule active! Atoms will be added to each." << endl;
    656654  cout << Verbose(0) << "INPUT: ";
     
    663661
    664662    case 'a': // add atom
    665       for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) {
     663      for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
     664        if ((*ListRunner)->ActiveFlag) {
    666665        mol = *ListRunner;
    667666        cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
     
    671670
    672671    case 'b': // scale a bond
    673       for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) {
     672      for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
     673        if ((*ListRunner)->ActiveFlag) {
    674674        mol = *ListRunner;
    675675        cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
     
    693693
    694694    case 'c': // unit scaling of the metric
    695       for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) {
     695      for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
     696        if ((*ListRunner)->ActiveFlag) {
    696697        mol = *ListRunner;
    697698        cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
     
    709710
    710711    case 'l': // measure distances or angles
    711       for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) {
     712      for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
     713        if ((*ListRunner)->ActiveFlag) {
    712714        mol = *ListRunner;
    713715        cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
     
    717719
    718720    case 'r': // remove atom
    719       for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) {
     721      for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
     722        if ((*ListRunner)->ActiveFlag) {
    720723        mol = *ListRunner;
    721724        cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
     
    725728
    726729    case 'u': // change an atom's element
    727       for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) {
     730      for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
     731        if ((*ListRunner)->ActiveFlag) {
    728732        int Z;
    729733        mol = *ListRunner;
     
    749753static void ManipulateMolecules(periodentafel *periode, MoleculeListClass *molecules, config *configuration)
    750754{
    751   atom *first, *second, *third, *fourth;
    752   Vector **atoms;
     755  atom *first;
    753756  Vector x,y,z,n; // coordinates for absolute point in cell volume
    754   double a,b,c;
    755757  int j, axis, count, faktor;
    756758  char choice;  // menu choice char
    757   bool valid;
    758759  molecule *mol = NULL;
    759760  element **Elements;
     
    772773  cout << Verbose(0) << "all else - go back" << endl;
    773774  cout << Verbose(0) << "===============================================" << endl;
    774   if (molecules->NumberOfActiveMolecules() > 0)
     775  if (molecules->NumberOfActiveMolecules() > 1)
    775776    cout << Verbose(0) << "WARNING: There is more than one molecule active! Atoms will be added to each." << endl;
    776777  cout << Verbose(0) << "INPUT: ";
     
    783784
    784785    case 'd': // duplicate the periodic cell along a given axis, given times
    785       for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) {
     786      for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
     787        if ((*ListRunner)->ActiveFlag) {
    786788        mol = *ListRunner;
    787789        cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
     
    841843
    842844    case 'g': // center the atoms
    843       for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) {
     845      for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
     846        if ((*ListRunner)->ActiveFlag) {
    844847        mol = *ListRunner;
    845848        cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
     
    849852
    850853    case 'i': // align all atoms
    851       for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) {
     854      for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
     855        if ((*ListRunner)->ActiveFlag) {
    852856        mol = *ListRunner;
    853857        cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
     
    857861
    858862    case 'm': // mirror atoms along a given axis
    859       for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) {
     863      for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
     864        if ((*ListRunner)->ActiveFlag) {
    860865        mol = *ListRunner;
    861866        cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
     
    865870
    866871    case 'o': // create the connection matrix
    867       {
     872      for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
     873        if ((*ListRunner)->ActiveFlag) {
    868874        double bonddistance;
    869875        clock_t start,end;
     
    879885
    880886    case 't': // translate all atoms
    881      for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) {
     887      for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
     888        if ((*ListRunner)->ActiveFlag) {
    882889        mol = *ListRunner;
    883890        cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl;
    884891        cout << Verbose(0) << "Enter translation vector." << endl;
    885892        x.AskPosition(mol->cell_size,0);
    886         mol->Translate((const Vector *)&x);
     893        mol->Center.AddVector((const Vector *)&x);
    887894     }
    888895     break;
     
    906913{
    907914  char choice;  // menu choice char
    908   bool valid;
    909   Vector Center;
     915  Vector center;
    910916  int nr, count;
    911917  molecule *mol = NULL;
    912   char *molname = NULL;
    913   int length;
    914   char filename[MAXSTRINGSIZE];
    915 
    916   cout << Verbose(0) << "==========Edit MOLECULES=====================" << endl;
     918
     919  cout << Verbose(0) << "==========EDIT MOLECULES=====================" << endl;
    917920  cout << Verbose(0) << "c - create new molecule" << endl;
    918921  cout << Verbose(0) << "l - load molecule from xyz file" << endl;
    919922  cout << Verbose(0) << "n - change molecule's name" << endl;
    920923  cout << Verbose(0) << "N - give molecules filename" << endl;
    921   cout << Verbose(0) << "p - parse xyz file into molecule" << endl;
     924  cout << Verbose(0) << "p - parse atoms in xyz file into molecule" << endl;
    922925  cout << Verbose(0) << "r - remove a molecule" << endl;
    923926  cout << Verbose(0) << "all else - go back" << endl;
     
    935938      break;
    936939
    937     case 'l': // laod from XYZ file
    938       cout << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl;
    939       mol = new molecule(periode);
    940       do {
    941         cout << Verbose(0) << "Enter file name: ";
     940    case 'l': // load from XYZ file
     941      {
     942        char filename[MAXSTRINGSIZE];
     943        cout << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl;
     944        mol = new molecule(periode);
     945        do {
     946          cout << Verbose(0) << "Enter file name: ";
     947          cin >> filename;
     948        } while (!mol->AddXYZFile(filename));
     949        mol->SetNameFromFilename(filename);
     950        // center at set box dimensions
     951        mol->CenterEdge((ofstream *)&cout, &center);
     952        mol->cell_size[0] = center.x[0];
     953        mol->cell_size[1] = 0;
     954        mol->cell_size[2] = center.x[1];
     955        mol->cell_size[3] = 0;
     956        mol->cell_size[4] = 0;
     957        mol->cell_size[5] = center.x[2];
     958        molecules->insert(mol);
     959      }
     960      break;
     961
     962    case 'n':
     963      {
     964        char filename[MAXSTRINGSIZE];
     965        do {
     966          cout << Verbose(0) << "Enter index of molecule: ";
     967          cin >> nr;
     968          mol = molecules->ReturnIndex(nr);
     969        } while (mol == NULL);
     970        cout << Verbose(0) << "Enter name: ";
    942971        cin >> filename;
    943       } while (!mol->AddXYZFile(filename));
    944       mol->SetNameFromFilename(filename);
    945       // center at set box dimensions
    946       mol->CenterEdge((ofstream *)&cout, &Center);
    947       mol->cell_size[0] = Center.x[0];
    948       mol->cell_size[1] = 0;
    949       mol->cell_size[2] = Center.x[1];
    950       mol->cell_size[3] = 0;
    951       mol->cell_size[4] = 0;
    952       mol->cell_size[5] = Center.x[2];
    953       molecules->insert(mol);
    954       break;
    955 
    956     case 'n':
    957       do {
    958         cout << Verbose(0) << "Enter index of molecule: ";
    959         cin >> nr;
    960         mol = molecules->ReturnIndex(nr);
    961       } while (mol != NULL);
    962       cout << Verbose(0) << "Enter name: ";
    963       cin >> filename;
    964       strcpy(mol->name, filename);
     972        strcpy(mol->name, filename);
     973      }
    965974      break;
    966975
    967976    case 'N':
    968       do {
    969         cout << Verbose(0) << "Enter index of molecule: ";
    970         cin >> nr;
    971         mol = molecules->ReturnIndex(nr);
    972       } while (mol != NULL);
    973       cout << Verbose(0) << "Enter name: ";
    974       cin >> filename;
    975       mol->SetNameFromFilename(filename);
     977      {
     978        char filename[MAXSTRINGSIZE];
     979        do {
     980          cout << Verbose(0) << "Enter index of molecule: ";
     981          cin >> nr;
     982          mol = molecules->ReturnIndex(nr);
     983        } while (mol == NULL);
     984        cout << Verbose(0) << "Enter name: ";
     985        cin >> filename;
     986        mol->SetNameFromFilename(filename);
     987      }
    976988      break;
    977989
    978990    case 'p': // parse XYZ file
    979       mol = NULL;
    980       do {
    981         cout << Verbose(0) << "Enter index of molecule: ";
    982         cin >> nr;
    983         mol = molecules->ReturnIndex(nr);
    984       } while (mol == NULL);
    985       cout << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl;
    986       do {
    987         cout << Verbose(0) << "Enter file name: ";
    988         cin >> filename;
    989       } while (!mol->AddXYZFile(filename));
    990       mol->SetNameFromFilename(filename);
     991      {
     992        char filename[MAXSTRINGSIZE];
     993        mol = NULL;
     994        do {
     995          cout << Verbose(0) << "Enter index of molecule: ";
     996          cin >> nr;
     997          mol = molecules->ReturnIndex(nr);
     998        } while (mol == NULL);
     999        cout << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl;
     1000        do {
     1001          cout << Verbose(0) << "Enter file name: ";
     1002          cin >> filename;
     1003        } while (!mol->AddXYZFile(filename));
     1004        mol->SetNameFromFilename(filename);
     1005      }
    9911006      break;
    9921007
     
    9951010      cin >> nr;
    9961011      count = 1;
    997       MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin();
    998       for(; ((ListRunner != molecules->ListOfMolecules.end()) && (count < nr)); ListRunner++);
    999       mol = *ListRunner;
    1000       if (count == nr) {
    1001         molecules->ListOfMolecules.erase(ListRunner);
    1002         delete(mol);
    1003       }
     1012      for( MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
     1013        if (nr == (*ListRunner)->IndexNr) {
     1014          mol = *ListRunner;
     1015          molecules->ListOfMolecules.erase(ListRunner);
     1016          delete(mol);
     1017        }
    10041018      break;
    10051019  }
     
    10141028{
    10151029  char choice;  // menu choice char
    1016   bool valid;
    10171030
    10181031  cout << Verbose(0) << "===========MERGE MOLECULES=====================" << endl;
     1032  cout << Verbose(0) << "a - simple add of one molecule to another" << endl;
    10191033  cout << Verbose(0) << "e - embedding merge of two molecules" << endl;
    10201034  cout << Verbose(0) << "m - multi-merge of all molecules" << endl;
     
    10311045      break;
    10321046
     1047    case 'a':
     1048      {
     1049        int src, dest;
     1050        molecule *srcmol = NULL, *destmol = NULL;
     1051        {
     1052          do {
     1053            cout << Verbose(0) << "Enter index of destination molecule: ";
     1054            cin >> dest;
     1055            destmol = molecules->ReturnIndex(dest);
     1056          } while ((destmol == NULL) && (dest != -1));
     1057          do {
     1058            cout << Verbose(0) << "Enter index of source molecule to add from: ";
     1059            cin >> src;
     1060            srcmol = molecules->ReturnIndex(src);
     1061          } while ((srcmol == NULL) && (src != -1));
     1062          if ((src != -1) && (dest != -1))
     1063            molecules->SimpleAdd(srcmol, destmol);
     1064        }
     1065      }
     1066      break;
     1067
    10331068    case 'e':
     1069      cout << Verbose(0) << "Not implemented yet." << endl;
    10341070      break;
    10351071
    10361072    case 'm':
     1073      {
     1074        int nr;
     1075        molecule *mol = NULL;
     1076        do {
     1077          cout << Verbose(0) << "Enter index of molecule to merge into: ";
     1078          cin >> nr;
     1079          mol = molecules->ReturnIndex(nr);
     1080        } while ((mol == NULL) && (nr != -1));
     1081        if (nr != -1) {
     1082          int N = molecules->ListOfMolecules.size()-1;
     1083          int *src = new int(N);
     1084          for(MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
     1085            if ((*ListRunner)->IndexNr != nr)
     1086              src[N++] = (*ListRunner)->IndexNr;       
     1087          molecules->SimpleMultiMerge(mol, src, N);
     1088          delete[](src);
     1089        }
     1090      }
    10371091      break;
    10381092
    10391093    case 's':
     1094      cout << Verbose(0) << "Not implemented yet." << endl;
    10401095      break;
    10411096
    10421097    case 't':
     1098      {
     1099        int src, dest;
     1100        molecule *srcmol = NULL, *destmol = NULL;
     1101        {
     1102          do {
     1103            cout << Verbose(0) << "Enter index of destination molecule: ";
     1104            cin >> dest;
     1105            destmol = molecules->ReturnIndex(dest);
     1106          } while ((destmol == NULL) && (dest != -1));
     1107          do {
     1108            cout << Verbose(0) << "Enter index of source molecule to merge into: ";
     1109            cin >> src;
     1110            srcmol = molecules->ReturnIndex(src);
     1111          } while ((srcmol == NULL) && (src != -1));
     1112          if ((src != -1) && (dest != -1))
     1113            molecules->SimpleMerge(srcmol, destmol);
     1114        }
     1115      }
    10431116      break;
    10441117  }
     
    11401213  molecule *mol = new molecule(periode);
    11411214
    1142   // merge all molecules in MoleculeListClass into this molecule
     1215  // translate each to its center and merge all molecules in MoleculeListClass into this molecule
    11431216  int N = molecules->ListOfMolecules.size();
    11441217  int *src = new int(N);
    11451218  N=0;
    1146   for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
     1219  for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) {
    11471220    src[N++] = (*ListRunner)->IndexNr;
     1221    (*ListRunner)->Translate(&(*ListRunner)->Center);
     1222  }
    11481223  molecules->SimpleMultiAdd(mol, src, N);
     1224  delete[](src);
     1225  // ... and translate back
     1226  for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) {
     1227    (*ListRunner)->Center.Scale(-1.);
     1228    (*ListRunner)->Translate(&(*ListRunner)->Center);
     1229    (*ListRunner)->Center.Scale(-1.);
     1230  }
    11491231
    11501232  cout << Verbose(0) << "Storing configuration ... " << endl;
     
    11521234  mol->CalculateOrbitals(*configuration);
    11531235  configuration->InitMaxMinStopStep = configuration->MaxMinStopStep = configuration->MaxPsiDouble;
    1154   strcpy(filename, ConfigFileName);
    11551236  if (ConfigFileName != NULL) { // test the file name
    1156     output.open(ConfigFileName, ios::trunc);
     1237    strcpy(filename, ConfigFileName);
     1238    output.open(filename, ios::trunc);
    11571239  } else if (strlen(configuration->configname) != 0) {
    11581240    strcpy(filename, configuration->configname);
     
    12231305 * \return exit code (0 - successful, all else - something's wrong)
    12241306 */
    1225 static int ParseCommandLineOptions(int argc, char **argv, MoleculeListClass *&molecules, periodentafel *&periode, config& configuration, char *&ConfigFileName, char *&PathToDatabases)
     1307static int ParseCommandLineOptions(int argc, char **argv, MoleculeListClass *&molecules, periodentafel *&periode, config& configuration, char *ConfigFileName, char *&PathToDatabases)
    12261308{
    12271309  Vector x,y,z,n;  // coordinates for absolute point in cell volume
     
    12421324  // simply create a new molecule, wherein the config file is loaded and the manipulation takes place
    12431325  molecule *mol = new molecule(periode);
     1326  mol->ActiveFlag = true;
    12441327  molecules->insert(mol);
    12451328
     
    12761359            cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl;
    12771360            cout << "\t-P <file>\tParse given forces file and append as an MD step to config file via Verlet." << endl;
     1361            cout << "\t-L <step0> <step1> <prefix>\tStore a linear interpolation between two configurations <step0> and <step1> into single config files with prefix <prefix> and as Trajectories into the current config file." << endl;
    12781362            cout << "\t-r\t\tConvert file from an old pcp syntax." << endl;
    12791363            cout << "\t-R\t\tRemove all atoms out of sphere around a given one." << endl;
     
    13371421        } else {
    13381422          cout << "Empty configuration file." << endl;
    1339           ConfigFileName = argv[1];
     1423          strcpy(ConfigFileName, argv[1]);
    13401424          config_present = empty;
    13411425          output.close();
     
    13431427      } else {
    13441428        test.close();
    1345         ConfigFileName = argv[1];
     1429        strcpy(ConfigFileName, argv[1]);
    13461430        cout << Verbose(1) << "Specified config file found, parsing ... ";
    13471431        switch (configuration.TestSyntax(ConfigFileName, periode, mol)) {
     
    15001584                LinkedCell LCList(mol, atof(argv[argptr]));    // \NOTE not twice the radius??
    15011585                Find_non_convex_border((ofstream *)&cout, mol, &T, &LCList, argv[argptr+1], atof(argv[argptr]));
    1502                 //FindDistributionOfEllipsoids((ofstream *)&cout, &T, &LCList, N, number, filename.c_str());
     1586                FindDistributionOfEllipsoids((ofstream *)&cout, &T, &LCList, N, number, filename.c_str());
    15031587                argptr+=2;
    15041588              }
     
    15211605              }
    15221606              break;
     1607            case 'L':
     1608              ExitFlag = 1;
     1609              SaveFlag = true;
     1610              cout << Verbose(1) << "Linear interpolation between configuration " << argv[argptr] << " and " << argv[argptr+1] << "." << endl;
     1611              if (!mol->LinearInterpolationBetweenConfiguration((ofstream *)&cout, atoi(argv[argptr]), atoi(argv[argptr+1]), argv[argptr+2], configuration))
     1612                cout << Verbose(2) << "Could not store " << argv[argptr+2] << " files." << endl;
     1613              else
     1614                cout << Verbose(2) << "Steps created and " << argv[argptr+2] << " files stored." << endl;
     1615              argptr+=3;
     1616              break;
    15231617            case 'P':
    15241618              ExitFlag = 1;
     
    15291623                SaveFlag = true;
    15301624                cout << Verbose(1) << "Parsing forces file and Verlet integrating." << endl;
    1531                 if (!mol->VerletForceIntegration(argv[argptr], configuration.Deltat, configuration.GetIsAngstroem()))
     1625                if (!mol->VerletForceIntegration((ofstream *)&cout, argv[argptr], configuration))
    15321626                  cout << Verbose(2) << "File not found." << endl;
    15331627                else
     
    16501744              ExitFlag = 1;
    16511745              SaveFlag = true;
    1652               cout << Verbose(1) << "Centering atoms in origin." << endl;
    1653               mol->CenterOrigin((ofstream *)&cout, &x);
     1746              cout << Verbose(1) << "Centering atoms on edge and setting box dimensions." << endl;
     1747              mol->CenterEdge((ofstream *)&cout, &x);
    16541748              mol->SetBoxDimension(&x);
    16551749              break;
     
    18311925  molecule *mol = NULL;
    18321926  config configuration;
    1833   double tmp1;
    1834   atom *first, *second;
    18351927  char choice;  // menu choice char
    18361928  Vector x,y,z,n;  // coordinates for absolute point in cell volume
    1837   bool valid; // flag if input was valid or not
    18381929  ifstream test;
    18391930  ofstream output;
    18401931  string line;
    1841   char *ConfigFileName = NULL;
     1932  char ConfigFileName[MAXSTRINGSIZE];
    18421933  char *ElementsFileName = NULL;
    1843   int Z;
    1844   int j, axis, count, faktor;
     1934  int j;
    18451935
    18461936  // =========================== PARSE COMMAND LINE OPTIONS ====================================
     1937  ConfigFileName[0] = '\0';
    18471938  j = ParseCommandLineOptions(argc, argv, molecules, periode, configuration, ConfigFileName, ElementsFileName);
    18481939  if (j == 1) return 0; // just for -v and -h options
     
    18611952    molecules->insert(mol);
    18621953  }
     1954  if (strlen(ConfigFileName) == 0)
     1955    strcpy(ConfigFileName, DEFAULTCONFIG);
     1956   
    18631957
    18641958  // =========================== START INTERACTIVE SESSION ====================================
     
    18721966    cout << Verbose(0) << "============Menu===============================" << endl;
    18731967    cout << Verbose(0) << "a - set molecule (in)active" << endl;
    1874     cout << Verbose(0) << "e - edit new molecules" << endl;
     1968    cout << Verbose(0) << "e - edit molecules (load, parse, save)" << endl;
    18751969    cout << Verbose(0) << "g - globally manipulate atoms in molecule" << endl;
    18761970    cout << Verbose(0) << "M - Merge molecules" << endl;
     
    18911985          cout << "Enter index of molecule: ";
    18921986          cin >> j;
    1893           count = 1;
    1894           MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin();
    1895           for(; ((ListRunner != molecules->ListOfMolecules.end()) && (count < j)); ListRunner++);
    1896           if (count == j)
    1897             (*ListRunner)->ActiveFlag = !(*ListRunner)->ActiveFlag;
     1987          for(MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
     1988            if ((*ListRunner)->IndexNr == j)
     1989              (*ListRunner)->ActiveFlag = !(*ListRunner)->ActiveFlag;
    18981990        }
    18991991        break;
  • src/config.cpp

    r375b458 r51c910  
    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  ThermostatImplemented = (int *) Malloc((MaxThermostats)*(sizeof(int)), "IonsInitRead: *ThermostatImplemented");
     21  ThermostatNames = (char **) Malloc((MaxThermostats)*(sizeof(char *)), "IonsInitRead: *ThermostatNames");
     22  for (int j=0;j<MaxThermostats;j++)
     23    ThermostatNames[j] = (char *) MallocString(12*(sizeof(char)), "IonsInitRead: ThermostatNames[]");
     24  Thermostat = 4;
     25  alpha = 0.;
     26  ScaleTempStep = 25;
     27  TempFrequency = 2.5;
     28  strcpy(mainname,"pcp");
     29  strcpy(defaultpath,"not specified");
     30  strcpy(pseudopotpath,"not specified");
     31  configpath[0]='\0';
     32  configname[0]='\0';
     33  basis="3-21G";
     34 
     35
     36  strcpy(ThermostatNames[0],"None");
     37  ThermostatImplemented[0] = 1;
     38  strcpy(ThermostatNames[1],"Woodcock");
     39  ThermostatImplemented[1] = 1;
     40  strcpy(ThermostatNames[2],"Gaussian");
     41  ThermostatImplemented[2] = 1;
     42  strcpy(ThermostatNames[3],"Langevin");
     43  ThermostatImplemented[3] = 1;
     44  strcpy(ThermostatNames[4],"Berendsen");
     45  ThermostatImplemented[4] = 1;
     46  strcpy(ThermostatNames[5],"NoseHoover");
     47  ThermostatImplemented[5] = 1;
     48
     49  FastParsing = false;
     50  ProcPEGamma=8;
     51  ProcPEPsi=1;
     52  DoOutVis=0;
     53  DoOutMes=1;
     54  DoOutNICS=0;
     55  DoOutOrbitals=0;
     56  DoOutCurrent=0;
     57  DoPerturbation=0;
     58  DoFullCurrent=0;
     59  DoWannier=0;
     60  DoConstrainedMD=0;
     61  CommonWannier=0;
     62  SawtoothStart=0.01;
     63  VectorPlane=0;
     64  VectorCut=0;
     65  UseAddGramSch=1;
     66  Seed=1;
     67
     68  MaxOuterStep=0;
     69  Deltat=0.01;
     70  OutVisStep=10;
     71  OutSrcStep=5;
     72  TargetTemp=0.00095004455;
     73  ScaleTempStep=25;
     74  MaxPsiStep=0;
     75  EpsWannier=1e-7;
     76
     77  MaxMinStep=100;
     78  RelEpsTotalEnergy=1e-7;
     79  RelEpsKineticEnergy=1e-5;
     80  MaxMinStopStep=1;
     81  MaxMinGapStopStep=0;
     82  MaxInitMinStep=100;
     83  InitRelEpsTotalEnergy=1e-5;
     84  InitRelEpsKineticEnergy=1e-4;
     85  InitMaxMinStopStep=1;
     86  InitMaxMinGapStopStep=0;
     87
     88  //BoxLength[NDIM*NDIM];
     89
     90  ECut=128.;
     91  MaxLevel=5;
     92  RiemannTensor=0;
     93  LevRFactor=0;
     94  RiemannLevel=0;
     95  Lev0Factor=2;
     96  RTActualUse=0;
     97  PsiType=0;
     98  MaxPsiDouble=0;
     99  PsiMaxNoUp=0;
     100  PsiMaxNoDown=0;
     101  AddPsis=0;
     102
     103  RCut=20.;
     104  StructOpt=0;
     105  IsAngstroem=1;
     106  RelativeCoord=0;
     107  MaxTypes=0;
    85108};
    86109
     
    90113config::~config()
    91114{
    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");
     115  Free((void **)&mainname, "config::~config: *mainname");
     116  Free((void **)&defaultpath, "config::~config: *defaultpath");
     117  Free((void **)&pseudopotpath, "config::~config: *pseudopotpath");
     118  Free((void **)&configpath, "config::~config: *configpath");
     119  Free((void **)&configname, "config::~config: *configname");
    97120};
     121
     122/** Readin of Thermostat related values from parameter file.
     123 * \param *source parameter file
     124 */
     125void config::InitThermostats(ifstream *source)
     126{
     127  char *thermo = MallocString(12, "IonsInitRead: thermo");
     128  int verbose = 0;
     129
     130  // read desired Thermostat from file along with needed additional parameters
     131  if (ParseForParameter(verbose,source,"Thermostat", 0, 1, 1, string_type, thermo, 1, optional)) {
     132    if (strcmp(thermo, ThermostatNames[0]) == 0) { // None
     133      if (ThermostatImplemented[0] == 1) {
     134        Thermostat = None;
     135      } else {
     136        cout << Verbose(1) << "Warning: " << ThermostatNames[0] << " thermostat not implemented, falling back to None." << endl;
     137        Thermostat = None;
     138      }
     139    } else if (strcmp(thermo, ThermostatNames[1]) == 0) { // Woodcock
     140      if (ThermostatImplemented[1] == 1) {
     141        Thermostat = Woodcock;
     142        ParseForParameter(verbose,source,"Thermostat", 0, 2, 1, int_type, &ScaleTempStep, 1, critical); // read scaling frequency
     143      } else {
     144        cout << Verbose(1) << "Warning: " << ThermostatNames[0] << " thermostat not implemented, falling back to None." << endl;
     145        Thermostat = None;
     146      }
     147    } else if (strcmp(thermo, ThermostatNames[2]) == 0) { // Gaussian
     148      if (ThermostatImplemented[2] == 1) {
     149        Thermostat = Gaussian;
     150        ParseForParameter(verbose,source,"Thermostat", 0, 2, 1, int_type, &ScaleTempStep, 1, critical); // read collision rate
     151      } else {
     152        cout << Verbose(1) << "Warning: " << ThermostatNames[0] << " thermostat not implemented, falling back to None." << endl;
     153        Thermostat = None;
     154      }
     155    } else if (strcmp(thermo, ThermostatNames[3]) == 0) { // Langevin
     156      if (ThermostatImplemented[3] == 1) {
     157        Thermostat = Langevin;
     158        ParseForParameter(verbose,source,"Thermostat", 0, 2, 1, double_type, &TempFrequency, 1, critical); // read gamma
     159        if (ParseForParameter(verbose,source,"Thermostat", 0, 3, 1, double_type, &alpha, 1, optional)) {
     160          cout << Verbose(2) << "Extended Stochastic Thermostat detected with interpolation coefficient " << alpha << "." << endl;
     161        } else {
     162          alpha = 1.;
     163        }
     164      } else {
     165        cout << Verbose(1) << "Warning: " << ThermostatNames[0] << " thermostat not implemented, falling back to None." << endl;
     166        Thermostat = None;
     167      }
     168    } else if (strcmp(thermo, ThermostatNames[4]) == 0) { // Berendsen
     169      if (ThermostatImplemented[4] == 1) {
     170        Thermostat = Berendsen;
     171        ParseForParameter(verbose,source,"Thermostat", 0, 2, 1, double_type, &TempFrequency, 1, critical); // read \tau_T
     172      } else {
     173        cout << Verbose(1) << "Warning: " << ThermostatNames[0] << " thermostat not implemented, falling back to None." << endl;
     174        Thermostat = None;
     175      }
     176    } else if (strcmp(thermo, ThermostatNames[5]) == 0) { // Nose-Hoover
     177      if (ThermostatImplemented[5] == 1) {
     178        Thermostat = NoseHoover;
     179        ParseForParameter(verbose,source,"Thermostat", 0, 2, 1, double_type, &HooverMass, 1, critical); // read Hoovermass
     180        alpha = 0.;
     181      } else {
     182        cout << Verbose(1) << "Warning: " << ThermostatNames[0] << " thermostat not implemented, falling back to None." << endl;
     183        Thermostat = None;
     184      }
     185    } else {
     186      cout << Verbose(1) << " Warning: thermostat name was not understood!" << endl;
     187      Thermostat = None;
     188    }
     189  } else {
     190    if ((MaxOuterStep > 0) && (TargetTemp != 0))
     191      cout << Verbose(2) <<  "No thermostat chosen despite finite temperature MD, falling back to None." << endl;
     192    Thermostat = None;
     193  }
     194  Free((void **)&thermo, "InitThermostats: thermo");
     195};
     196
    98197
    99198/** Displays menu for editing each entry of the config file.
     
    103202void config::Edit()
    104203{
    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');
     204  char choice;
     205
     206  do {
     207    cout << Verbose(0) << "===========EDIT CONFIGURATION============================" << endl;
     208    cout << Verbose(0) << " A - mainname (prefix for all runtime files)" << endl;
     209    cout << Verbose(0) << " B - Default path (for runtime files)" << endl;
     210    cout << Verbose(0) << " C - Path of pseudopotential files" << endl;
     211    cout << Verbose(0) << " D - Number of coefficient sharing processes" << endl;
     212    cout << Verbose(0) << " E - Number of wave function sharing processes" << endl;
     213    cout << Verbose(0) << " F - 0: Don't output density for OpenDX, 1: do" << endl;
     214    cout << Verbose(0) << " G - 0: Don't output physical data, 1: do" << endl;
     215    cout << Verbose(0) << " H - 0: Don't output densities of each unperturbed orbital for OpenDX, 1: do" << endl;
     216    cout << Verbose(0) << " I - 0: Don't output current density for OpenDX, 1: do" << endl;
     217    cout << Verbose(0) << " J - 0: Don't do the full current calculation, 1: do" << endl;
     218    cout << Verbose(0) << " K - 0: Don't do perturbation calculation to obtain susceptibility and shielding, 1: do" << endl;
     219    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;
     220    cout << Verbose(0) << " M - Absolute begin of unphysical sawtooth transfer for position operator within cell" << endl;
     221    cout << Verbose(0) << " N - (0,1,2) x,y,z-plane to do two-dimensional current vector cut" << endl;
     222    cout << Verbose(0) << " O - Absolute position along vector cut axis for cut plane" << endl;
     223    cout << Verbose(0) << " P - Additional Gram-Schmidt-Orthonormalization to stabilize numerics" << endl;
     224    cout << Verbose(0) << " Q - Initial integer value of random number generator" << endl;
     225    cout << Verbose(0) << " R - for perturbation 0, for structure optimization defines upper limit of iterations" << endl;
     226    cout << Verbose(0) << " T - Output visual after ...th step" << endl;
     227    cout << Verbose(0) << " U - Output source densities of wave functions after ...th step" << endl;
     228    cout << Verbose(0) << " X - minimization iterations per wave function, if unsure leave at default value 0" << endl;
     229    cout << Verbose(0) << " Y - tolerance value for total spread in iterative Jacobi diagonalization" << endl;
     230    cout << Verbose(0) << " Z - Maximum number of minimization iterations" << endl;
     231    cout << Verbose(0) << " a - Relative change in total energy to stop min. iteration" << endl;
     232    cout << Verbose(0) << " b - Relative change in kinetic energy to stop min. iteration" << endl;
     233    cout << Verbose(0) << " c - Check stop conditions every ..th step during min. iteration" << endl;
     234    cout << Verbose(0) << " e - Maximum number of minimization iterations during initial level" << endl;
     235    cout << Verbose(0) << " f - Relative change in total energy to stop min. iteration during initial level" << endl;
     236    cout << Verbose(0) << " g - Relative change in kinetic energy to stop min. iteration during initial level" << endl;
     237    cout << Verbose(0) << " h - Check stop conditions every ..th step during min. iteration during initial level" << endl;
     238//    cout << Verbose(0) << " j - six lower diagonal entries of matrix, defining the unit cell" << endl;
     239    cout << Verbose(0) << " k - Energy cutoff of plane wave basis in Hartree" << endl;
     240    cout << Verbose(0) << " l - Maximum number of levels in multi-level-ansatz" << endl;
     241    cout << Verbose(0) << " m - Factor by which grid nodes increase between standard and upper level" << endl;
     242    cout << Verbose(0) << " n - 0: Don't use RiemannTensor, 1: Do" << endl;
     243    cout << Verbose(0) << " o - Factor by which grid nodes increase between Riemann and standard(?) level" << endl;
     244    cout << Verbose(0) << " p - Number of Riemann levels" << endl;
     245    cout << Verbose(0) << " r - 0: Don't Use RiemannTensor, 1: Do" << endl;
     246    cout << Verbose(0) << " s - 0: Doubly occupied orbitals, 1: Up-/Down-Orbitals" << endl;
     247    cout << Verbose(0) << " t - Number of orbitals (depends pn SpinType)" << endl;
     248    cout << Verbose(0) << " u - Number of SpinUp orbitals (depends on SpinType)" << endl;
     249    cout << Verbose(0) << " v - Number of SpinDown orbitals (depends on SpinType)" << endl;
     250    cout << Verbose(0) << " w - Number of additional, unoccupied orbitals" << endl;
     251    cout << Verbose(0) << " x - radial cutoff for ewald summation in Bohrradii" << endl;
     252    cout << Verbose(0) << " y - 0: Don't do structure optimization beforehand, 1: Do" << endl;
     253    cout << Verbose(0) << " z - 0: Units are in Bohr radii, 1: units are in Aengstrom" << endl;
     254    cout << Verbose(0) << " i - 0: Coordinates given in file are absolute, 1: ... are relative to unit cell" << endl;
     255    cout << Verbose(0) << "=========================================================" << endl;
     256    cout << Verbose(0) << "INPUT: ";
     257    cin >> choice;
     258
     259    switch (choice) {
     260        case 'A': // mainname
     261          cout << Verbose(0) << "Old: " << config::mainname << "\t new: ";
     262          cin >> config::mainname;
     263          break;
     264        case 'B': // defaultpath
     265          cout << Verbose(0) << "Old: " << config::defaultpath << "\t new: ";
     266          cin >> config::defaultpath;
     267          break;
     268        case 'C': // pseudopotpath
     269          cout << Verbose(0) << "Old: " << config::pseudopotpath << "\t new: ";
     270          cin >> config::pseudopotpath;
     271          break;
     272
     273        case 'D': // ProcPEGamma
     274          cout << Verbose(0) << "Old: " << config::ProcPEGamma << "\t new: ";
     275          cin >> config::ProcPEGamma;
     276          break;
     277        case 'E': // ProcPEPsi
     278          cout << Verbose(0) << "Old: " << config::ProcPEPsi << "\t new: ";
     279          cin >> config::ProcPEPsi;
     280          break;
     281        case 'F': // DoOutVis
     282          cout << Verbose(0) << "Old: " << config::DoOutVis << "\t new: ";
     283          cin >> config::DoOutVis;
     284          break;
     285        case 'G': // DoOutMes
     286          cout << Verbose(0) << "Old: " << config::DoOutMes << "\t new: ";
     287          cin >> config::DoOutMes;
     288          break;
     289        case 'H': // DoOutOrbitals
     290          cout << Verbose(0) << "Old: " << config::DoOutOrbitals << "\t new: ";
     291          cin >> config::DoOutOrbitals;
     292          break;
     293        case 'I': // DoOutCurrent
     294          cout << Verbose(0) << "Old: " << config::DoOutCurrent << "\t new: ";
     295          cin >> config::DoOutCurrent;
     296          break;
     297        case 'J': // DoFullCurrent
     298          cout << Verbose(0) << "Old: " << config::DoFullCurrent << "\t new: ";
     299          cin >> config::DoFullCurrent;
     300          break;
     301        case 'K': // DoPerturbation
     302          cout << Verbose(0) << "Old: " << config::DoPerturbation << "\t new: ";
     303          cin >> config::DoPerturbation;
     304          break;
     305        case 'L': // CommonWannier
     306          cout << Verbose(0) << "Old: " << config::CommonWannier << "\t new: ";
     307          cin >> config::CommonWannier;
     308          break;
     309        case 'M': // SawtoothStart
     310          cout << Verbose(0) << "Old: " << config::SawtoothStart << "\t new: ";
     311          cin >> config::SawtoothStart;
     312          break;
     313        case 'N': // VectorPlane
     314          cout << Verbose(0) << "Old: " << config::VectorPlane << "\t new: ";
     315          cin >> config::VectorPlane;
     316          break;
     317        case 'O': // VectorCut
     318          cout << Verbose(0) << "Old: " << config::VectorCut << "\t new: ";
     319          cin >> config::VectorCut;
     320          break;
     321        case 'P': // UseAddGramSch
     322          cout << Verbose(0) << "Old: " << config::UseAddGramSch << "\t new: ";
     323          cin >> config::UseAddGramSch;
     324          break;
     325        case 'Q': // Seed
     326          cout << Verbose(0) << "Old: " << config::Seed << "\t new: ";
     327          cin >> config::Seed;
     328          break;
     329
     330        case 'R': // MaxOuterStep
     331          cout << Verbose(0) << "Old: " << config::MaxOuterStep << "\t new: ";
     332          cin >> config::MaxOuterStep;
     333          break;
     334        case 'T': // OutVisStep
     335          cout << Verbose(0) << "Old: " << config::OutVisStep << "\t new: ";
     336          cin >> config::OutVisStep;
     337          break;
     338        case 'U': // OutSrcStep
     339          cout << Verbose(0) << "Old: " << config::OutSrcStep << "\t new: ";
     340          cin >> config::OutSrcStep;
     341          break;
     342        case 'X': // MaxPsiStep
     343          cout << Verbose(0) << "Old: " << config::MaxPsiStep << "\t new: ";
     344          cin >> config::MaxPsiStep;
     345          break;
     346        case 'Y': // EpsWannier
     347          cout << Verbose(0) << "Old: " << config::EpsWannier << "\t new: ";
     348          cin >> config::EpsWannier;
     349          break;
     350
     351        case 'Z': // MaxMinStep
     352          cout << Verbose(0) << "Old: " << config::MaxMinStep << "\t new: ";
     353          cin >> config::MaxMinStep;
     354          break;
     355        case 'a': // RelEpsTotalEnergy
     356          cout << Verbose(0) << "Old: " << config::RelEpsTotalEnergy << "\t new: ";
     357          cin >> config::RelEpsTotalEnergy;
     358          break;
     359        case 'b': // RelEpsKineticEnergy
     360          cout << Verbose(0) << "Old: " << config::RelEpsKineticEnergy << "\t new: ";
     361          cin >> config::RelEpsKineticEnergy;
     362          break;
     363        case 'c': // MaxMinStopStep
     364          cout << Verbose(0) << "Old: " << config::MaxMinStopStep << "\t new: ";
     365          cin >> config::MaxMinStopStep;
     366          break;
     367        case 'e': // MaxInitMinStep
     368          cout << Verbose(0) << "Old: " << config::MaxInitMinStep << "\t new: ";
     369          cin >> config::MaxInitMinStep;
     370          break;
     371        case 'f': // InitRelEpsTotalEnergy
     372          cout << Verbose(0) << "Old: " << config::InitRelEpsTotalEnergy << "\t new: ";
     373          cin >> config::InitRelEpsTotalEnergy;
     374          break;
     375        case 'g': // InitRelEpsKineticEnergy
     376          cout << Verbose(0) << "Old: " << config::InitRelEpsKineticEnergy << "\t new: ";
     377          cin >> config::InitRelEpsKineticEnergy;
     378          break;
     379        case 'h': // InitMaxMinStopStep
     380          cout << Verbose(0) << "Old: " << config::InitMaxMinStopStep << "\t new: ";
     381          cin >> config::InitMaxMinStopStep;
     382          break;
     383
     384//        case 'j': // BoxLength
     385//          cout << Verbose(0) << "enter lower triadiagonalo form of basis matrix" << endl << endl;
     386//          for (int i=0;i<6;i++) {
     387//            cout << Verbose(0) << "Cell size" << i << ": ";
     388//            cin >> mol->cell_size[i];
     389//          }
     390//          break;
     391
     392        case 'k': // ECut
     393          cout << Verbose(0) << "Old: " << config::ECut << "\t new: ";
     394          cin >> config::ECut;
     395          break;
     396        case 'l': // MaxLevel
     397          cout << Verbose(0) << "Old: " << config::MaxLevel << "\t new: ";
     398          cin >> config::MaxLevel;
     399          break;
     400        case 'm': // RiemannTensor
     401          cout << Verbose(0) << "Old: " << config::RiemannTensor << "\t new: ";
     402          cin >> config::RiemannTensor;
     403          break;
     404        case 'n': // LevRFactor
     405          cout << Verbose(0) << "Old: " << config::LevRFactor << "\t new: ";
     406          cin >> config::LevRFactor;
     407          break;
     408        case 'o': // RiemannLevel
     409          cout << Verbose(0) << "Old: " << config::RiemannLevel << "\t new: ";
     410          cin >> config::RiemannLevel;
     411          break;
     412        case 'p': // Lev0Factor
     413          cout << Verbose(0) << "Old: " << config::Lev0Factor << "\t new: ";
     414          cin >> config::Lev0Factor;
     415          break;
     416        case 'r': // RTActualUse
     417          cout << Verbose(0) << "Old: " << config::RTActualUse << "\t new: ";
     418          cin >> config::RTActualUse;
     419          break;
     420        case 's': // PsiType
     421          cout << Verbose(0) << "Old: " << config::PsiType << "\t new: ";
     422          cin >> config::PsiType;
     423          break;
     424        case 't': // MaxPsiDouble
     425          cout << Verbose(0) << "Old: " << config::MaxPsiDouble << "\t new: ";
     426          cin >> config::MaxPsiDouble;
     427          break;
     428        case 'u': // PsiMaxNoUp
     429          cout << Verbose(0) << "Old: " << config::PsiMaxNoUp << "\t new: ";
     430          cin >> config::PsiMaxNoUp;
     431          break;
     432        case 'v': // PsiMaxNoDown
     433          cout << Verbose(0) << "Old: " << config::PsiMaxNoDown << "\t new: ";
     434          cin >> config::PsiMaxNoDown;
     435          break;
     436        case 'w': // AddPsis
     437          cout << Verbose(0) << "Old: " << config::AddPsis << "\t new: ";
     438          cin >> config::AddPsis;
     439          break;
     440
     441        case 'x': // RCut
     442          cout << Verbose(0) << "Old: " << config::RCut << "\t new: ";
     443          cin >> config::RCut;
     444          break;
     445        case 'y': // StructOpt
     446          cout << Verbose(0) << "Old: " << config::StructOpt << "\t new: ";
     447          cin >> config::StructOpt;
     448          break;
     449        case 'z': // IsAngstroem
     450          cout << Verbose(0) << "Old: " << config::IsAngstroem << "\t new: ";
     451          cin >> config::IsAngstroem;
     452          break;
     453        case 'i': // RelativeCoord
     454          cout << Verbose(0) << "Old: " << config::RelativeCoord << "\t new: ";
     455          cin >> config::RelativeCoord;
     456          break;
     457    };
     458  } while (choice != 'q');
    360459};
    361460
     
    368467int config::TestSyntax(char *filename, periodentafel *periode, molecule *mol)
    369468{
    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;
     469  int test;
     470  ifstream file(filename);
     471
     472  // search file for keyword: ProcPEGamma (new syntax)
     473  if (ParseForParameter(1,&file,"ProcPEGamma", 0, 1, 1, int_type, &test, 1, optional)) {
     474    file.close();
     475    return 1;
     476  }
     477  // search file for keyword: ProcsGammaPsi (old syntax)
     478  if (ParseForParameter(1,&file,"ProcsGammaPsi", 0, 1, 1, int_type, &test, 1, optional)) {
     479    file.close();
     480    return 0;
     481  }
     482  file.close();
     483  return -1;
    385484}
    386485
     
    390489bool config::GetIsAngstroem() const
    391490{
    392         return (IsAngstroem == 1);
     491  return (IsAngstroem == 1);
    393492};
    394493
     
    398497char * config::GetDefaultPath() const
    399498{
    400         return defaultpath;
     499  return defaultpath;
    401500};
    402501
     
    407506void config::SetDefaultPath(const char *path)
    408507{
    409         strcpy(defaultpath, path);
     508  strcpy(defaultpath, path);
    410509};
    411510
     
    415514void config::RetrieveConfigPathAndName(string filename)
    416515{
    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);
     516  char *ptr = NULL;
     517  char *buffer = new char[MAXSTRINGSIZE];
     518  strncpy(buffer, filename.c_str(), MAXSTRINGSIZE);
     519  int last = -1;
     520  for(last=MAXSTRINGSIZE;last--;) {
     521    if (buffer[last] == '/')
     522      break;
     523  }
     524  if (last == -1) { // no path in front, set to local directory.
     525    strcpy(configpath, "./");
     526    ptr = buffer;
     527  } else {
     528    strncpy(configpath, buffer, last+1);
     529    ptr = &buffer[last+1];
     530    if (last < 254)
     531      configpath[last+1]='\0';
     532  }
     533  strcpy(configname, ptr);
     534  cout << "Found configpath: " << configpath << ", dir slash was found at " << last << ", config name is " << configname << "." << endl;
     535  delete[](buffer);
    437536};
    438537
     
    445544void config::Load(char *filename, periodentafel *periode, molecule *mol)
    446545{
    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);
     546  ifstream *file = new ifstream(filename);
     547  if (file == NULL) {
     548    cerr << "ERROR: config file " << filename << " missing!" << endl;
     549    return;
     550  }
     551  RetrieveConfigPathAndName(filename);
     552  // ParseParameters
     553
     554  /* Oeffne Hauptparameterdatei */
     555  int di;
     556  double BoxLength[9];
     557  string zeile;
     558  string dummy;
     559  element *elementhash[MAX_ELEMENTS];
     560  char name[MAX_ELEMENTS];
     561  char keyword[MAX_ELEMENTS];
     562  int Z, No[MAX_ELEMENTS];
     563  int verbose = 0;
     564  double value[3];
     565 
     566  InitThermostats(file);
     567 
     568  /* Namen einlesen */
     569
     570  ParseForParameter(verbose,file, "mainname", 0, 1, 1, string_type, (config::mainname), 1, critical);
     571  ParseForParameter(verbose,file, "defaultpath", 0, 1, 1, string_type, (config::defaultpath), 1, critical);
     572  ParseForParameter(verbose,file, "pseudopotpath", 0, 1, 1, string_type, (config::pseudopotpath), 1, critical);
     573  ParseForParameter(verbose,file,"ProcPEGamma", 0, 1, 1, int_type, &(config::ProcPEGamma), 1, critical);
     574  ParseForParameter(verbose,file,"ProcPEPsi", 0, 1, 1, int_type, &(config::ProcPEPsi), 1, critical);
     575
     576  if (!ParseForParameter(verbose,file,"Seed", 0, 1, 1, int_type, &(config::Seed), 1, optional))
     577    config::Seed = 1;
     578
     579  if(!ParseForParameter(verbose,file,"DoOutOrbitals", 0, 1, 1, int_type, &(config::DoOutOrbitals), 1, optional)) {
     580    config::DoOutOrbitals = 0;
     581  } else {
     582    if (config::DoOutOrbitals < 0) config::DoOutOrbitals = 0;
     583    if (config::DoOutOrbitals > 1) config::DoOutOrbitals = 1;
     584  }
     585  ParseForParameter(verbose,file,"DoOutVis", 0, 1, 1, int_type, &(config::DoOutVis), 1, critical);
     586  if (config::DoOutVis < 0) config::DoOutVis = 0;
     587  if (config::DoOutVis > 1) config::DoOutVis = 1;
     588  if (!ParseForParameter(verbose,file,"VectorPlane", 0, 1, 1, int_type, &(config::VectorPlane), 1, optional))
     589    config::VectorPlane = -1;
     590  if (!ParseForParameter(verbose,file,"VectorCut", 0, 1, 1, double_type, &(config::VectorCut), 1, optional))
     591    config::VectorCut = 0.;
     592  ParseForParameter(verbose,file,"DoOutMes", 0, 1, 1, int_type, &(config::DoOutMes), 1, critical);
     593  if (config::DoOutMes < 0) config::DoOutMes = 0;
     594  if (config::DoOutMes > 1) config::DoOutMes = 1;
     595  if (!ParseForParameter(verbose,file,"DoOutCurr", 0, 1, 1, int_type, &(config::DoOutCurrent), 1, optional))
     596    config::DoOutCurrent = 0;
     597  if (config::DoOutCurrent < 0) config::DoOutCurrent = 0;
     598  if (config::DoOutCurrent > 1) config::DoOutCurrent = 1;
     599  ParseForParameter(verbose,file,"AddGramSch", 0, 1, 1, int_type, &(config::UseAddGramSch), 1, critical);
     600  if (config::UseAddGramSch < 0) config::UseAddGramSch = 0;
     601  if (config::UseAddGramSch > 2) config::UseAddGramSch = 2;
     602  if(!ParseForParameter(verbose,file,"DoWannier", 0, 1, 1, int_type, &(config::DoWannier), 1, optional)) {
     603    config::DoWannier = 0;
     604  } else {
     605    if (config::DoWannier < 0) config::DoWannier = 0;
     606    if (config::DoWannier > 1) config::DoWannier = 1;
     607  }
     608  if(!ParseForParameter(verbose,file,"CommonWannier", 0, 1, 1, int_type, &(config::CommonWannier), 1, optional)) {
     609    config::CommonWannier = 0;
     610  } else {
     611    if (config::CommonWannier < 0) config::CommonWannier = 0;
     612    if (config::CommonWannier > 4) config::CommonWannier = 4;
     613  }
     614  if(!ParseForParameter(verbose,file,"SawtoothStart", 0, 1, 1, double_type, &(config::SawtoothStart), 1, optional)) {
     615    config::SawtoothStart = 0.01;
     616  } else {
     617    if (config::SawtoothStart < 0.) config::SawtoothStart = 0.;
     618    if (config::SawtoothStart > 1.) config::SawtoothStart = 1.;
     619  }
     620 
     621  if (ParseForParameter(verbose,file,"DoConstrainedMD", 0, 1, 1, int_type, &(config::DoConstrainedMD), 1, optional))
     622    if (config::DoConstrainedMD < 0)
     623      config::DoConstrainedMD = 0;
     624  ParseForParameter(verbose,file,"MaxOuterStep", 0, 1, 1, int_type, &(config::MaxOuterStep), 1, critical);
     625  if (!ParseForParameter(verbose,file,"Deltat", 0, 1, 1, double_type, &(config::Deltat), 1, optional))
     626    config::Deltat = 1;
     627  ParseForParameter(verbose,file,"OutVisStep", 0, 1, 1, int_type, &(config::OutVisStep), 1, optional);
     628  ParseForParameter(verbose,file,"OutSrcStep", 0, 1, 1, int_type, &(config::OutSrcStep), 1, optional);
     629  ParseForParameter(verbose,file,"TargetTemp", 0, 1, 1, double_type, &(config::TargetTemp), 1, optional);
     630  //ParseForParameter(verbose,file,"Thermostat", 0, 1, 1, int_type, &(config::ScaleTempStep), 1, optional);
     631  if (!ParseForParameter(verbose,file,"EpsWannier", 0, 1, 1, double_type, &(config::EpsWannier), 1, optional))
     632    config::EpsWannier = 1e-8;
     633
     634  // stop conditions
     635  //if (config::MaxOuterStep <= 0) config::MaxOuterStep = 1;
     636  ParseForParameter(verbose,file,"MaxPsiStep", 0, 1, 1, int_type, &(config::MaxPsiStep), 1, critical);
     637  if (config::MaxPsiStep <= 0) config::MaxPsiStep = 3;
     638
     639  ParseForParameter(verbose,file,"MaxMinStep", 0, 1, 1, int_type, &(config::MaxMinStep), 1, critical);
     640  ParseForParameter(verbose,file,"RelEpsTotalE", 0, 1, 1, double_type, &(config::RelEpsTotalEnergy), 1, critical);
     641  ParseForParameter(verbose,file,"RelEpsKineticE", 0, 1, 1, double_type, &(config::RelEpsKineticEnergy), 1, critical);
     642  ParseForParameter(verbose,file,"MaxMinStopStep", 0, 1, 1, int_type, &(config::MaxMinStopStep), 1, critical);
     643  ParseForParameter(verbose,file,"MaxMinGapStopStep", 0, 1, 1, int_type, &(config::MaxMinGapStopStep), 1, critical);
     644  if (config::MaxMinStep <= 0) config::MaxMinStep = config::MaxPsiStep;
     645  if (config::MaxMinStopStep < 1) config::MaxMinStopStep = 1;
     646  if (config::MaxMinGapStopStep < 1) config::MaxMinGapStopStep = 1;
     647
     648  ParseForParameter(verbose,file,"MaxInitMinStep", 0, 1, 1, int_type, &(config::MaxInitMinStep), 1, critical);
     649  ParseForParameter(verbose,file,"InitRelEpsTotalE", 0, 1, 1, double_type, &(config::InitRelEpsTotalEnergy), 1, critical);
     650  ParseForParameter(verbose,file,"InitRelEpsKineticE", 0, 1, 1, double_type, &(config::InitRelEpsKineticEnergy), 1, critical);
     651  ParseForParameter(verbose,file,"InitMaxMinStopStep", 0, 1, 1, int_type, &(config::InitMaxMinStopStep), 1, critical);
     652  ParseForParameter(verbose,file,"InitMaxMinGapStopStep", 0, 1, 1, int_type, &(config::InitMaxMinGapStopStep), 1, critical);
     653  if (config::MaxInitMinStep <= 0) config::MaxInitMinStep = config::MaxPsiStep;
     654  if (config::InitMaxMinStopStep < 1) config::InitMaxMinStopStep = 1;
     655  if (config::InitMaxMinGapStopStep < 1) config::InitMaxMinGapStopStep = 1;
     656
     657  // Unit cell and magnetic field
     658  ParseForParameter(verbose,file, "BoxLength", 0, 3, 3, lower_trigrid, BoxLength, 1, critical); /* Lattice->RealBasis */
     659  mol->cell_size[0] = BoxLength[0];
     660  mol->cell_size[1] = BoxLength[3];
     661  mol->cell_size[2] = BoxLength[4];
     662  mol->cell_size[3] = BoxLength[6];
     663  mol->cell_size[4] = BoxLength[7];
     664  mol->cell_size[5] = BoxLength[8];
     665  if (1) fprintf(stderr,"\n");
     666
     667  ParseForParameter(verbose,file,"DoPerturbation", 0, 1, 1, int_type, &(config::DoPerturbation), 1, optional);
     668  ParseForParameter(verbose,file,"DoOutNICS", 0, 1, 1, int_type, &(config::DoOutNICS), 1, optional);
     669  if (!ParseForParameter(verbose,file,"DoFullCurrent", 0, 1, 1, int_type, &(config::DoFullCurrent), 1, optional))
     670    config::DoFullCurrent = 0;
     671  if (config::DoFullCurrent < 0) config::DoFullCurrent = 0;
     672  if (config::DoFullCurrent > 2) config::DoFullCurrent = 2;
     673  if (config::DoOutNICS < 0) config::DoOutNICS = 0;
     674  if (config::DoOutNICS > 2) config::DoOutNICS = 2;
     675  if (config::DoPerturbation == 0) {
     676    config::DoFullCurrent = 0;
     677    config::DoOutNICS = 0;
     678  }
     679
     680  ParseForParameter(verbose,file,"ECut", 0, 1, 1, double_type, &(config::ECut), 1, critical);
     681  ParseForParameter(verbose,file,"MaxLevel", 0, 1, 1, int_type, &(config::MaxLevel), 1, critical);
     682  ParseForParameter(verbose,file,"Level0Factor", 0, 1, 1, int_type, &(config::Lev0Factor), 1, critical);
     683  if (config::Lev0Factor < 2) {
     684    config::Lev0Factor = 2;
     685  }
     686  ParseForParameter(verbose,file,"RiemannTensor", 0, 1, 1, int_type, &di, 1, critical);
     687  if (di >= 0 && di < 2) {
     688    config::RiemannTensor = di;
     689  } else {
     690    fprintf(stderr, "0 <= RiemanTensor < 2: 0 UseNotRT, 1 UseRT");
     691    exit(1);
     692  }
     693  switch (config::RiemannTensor) {
     694    case 0: //UseNoRT
     695      if (config::MaxLevel < 2) {
     696        config::MaxLevel = 2;
     697      }
     698      config::LevRFactor = 2;
     699      config::RTActualUse = 0;
     700      break;
     701    case 1: // UseRT
     702      if (config::MaxLevel < 3) {
     703        config::MaxLevel = 3;
     704      }
     705      ParseForParameter(verbose,file,"RiemannLevel", 0, 1, 1, int_type, &(config::RiemannLevel), 1, critical);
     706      if (config::RiemannLevel < 2) {
     707        config::RiemannLevel = 2;
     708      }
     709      if (config::RiemannLevel > config::MaxLevel-1) {
     710        config::RiemannLevel = config::MaxLevel-1;
     711      }
     712      ParseForParameter(verbose,file,"LevRFactor", 0, 1, 1, int_type, &(config::LevRFactor), 1, critical);
     713      if (config::LevRFactor < 2) {
     714        config::LevRFactor = 2;
     715      }
     716      config::Lev0Factor = 2;
     717      config::RTActualUse = 2;
     718      break;
     719  }
     720  ParseForParameter(verbose,file,"PsiType", 0, 1, 1, int_type, &di, 1, critical);
     721  if (di >= 0 && di < 2) {
     722    config::PsiType = di;
     723  } else {
     724    fprintf(stderr, "0 <= PsiType < 2: 0 UseSpinDouble, 1 UseSpinUpDown");
     725    exit(1);
     726  }
     727  switch (config::PsiType) {
     728  case 0: // SpinDouble
     729    ParseForParameter(verbose,file,"MaxPsiDouble", 0, 1, 1, int_type, &(config::MaxPsiDouble), 1, critical);
     730    ParseForParameter(verbose,file,"AddPsis", 0, 1, 1, int_type, &(config::AddPsis), 1, optional);
     731    break;
     732  case 1: // SpinUpDown
     733    if (config::ProcPEGamma % 2) config::ProcPEGamma*=2;
     734    ParseForParameter(verbose,file,"PsiMaxNoUp", 0, 1, 1, int_type, &(config::PsiMaxNoUp), 1, critical);
     735    ParseForParameter(verbose,file,"PsiMaxNoDown", 0, 1, 1, int_type, &(config::PsiMaxNoDown), 1, critical);
     736    ParseForParameter(verbose,file,"AddPsis", 0, 1, 1, int_type, &(config::AddPsis), 1, optional);
     737    break;
     738  }
     739
     740  // IonsInitRead
     741
     742  ParseForParameter(verbose,file,"RCut", 0, 1, 1, double_type, &(config::RCut), 1, critical);
     743  ParseForParameter(verbose,file,"IsAngstroem", 0, 1, 1, int_type, &(config::IsAngstroem), 1, critical);
     744  ParseForParameter(verbose,file,"MaxTypes", 0, 1, 1, int_type, &(config::MaxTypes), 1, critical);
     745  if (!ParseForParameter(verbose,file,"RelativeCoord", 0, 1, 1, int_type, &(config::RelativeCoord) , 1, optional))
     746    config::RelativeCoord = 0;
     747  if (!ParseForParameter(verbose,file,"StructOpt", 0, 1, 1, int_type, &(config::StructOpt), 1, optional))
     748    config::StructOpt = 0;
     749  if (MaxTypes == 0) {
     750    cerr << "There are no atoms according to MaxTypes in this config file." << endl;
     751  } else {
     752    // prescan number of ions per type
     753    cout << Verbose(0) << "Prescanning ions per type: " << endl;
     754    for (int i=0; i < config::MaxTypes; i++) {
     755      sprintf(name,"Ion_Type%i",i+1);
     756      ParseForParameter(verbose,file, (const char*)name, 0, 1, 1, int_type, &No[i], 1, critical);
     757      ParseForParameter(verbose,file, name, 0, 2, 1, int_type, &Z, 1, critical);
     758      elementhash[i] = periode->FindElement(Z);
     759      cout << Verbose(1) << i << ". Z = " << elementhash[i]->Z << " with " << No[i] << " ions." << endl;
     760    }
     761    int repetition = 0; // which repeated keyword shall be read
     762
     763    map<int, atom *> AtomList[config::MaxTypes];
     764    if (!FastParsing) {
     765      // parse in trajectories
     766      bool status = true;
     767      atom *neues = NULL;
     768      while (status) {
     769        cout << "Currently parsing MD step " << repetition << "." << endl;
     770        for (int i=0; i < config::MaxTypes; i++) {
     771          sprintf(name,"Ion_Type%i",i+1);
     772          for(int j=0;j<No[i];j++) {
     773            sprintf(keyword,"%s_%i",name, j+1);
     774            if (repetition == 0) {
     775              neues = new atom();
     776              AtomList[i][j] = neues;
     777              neues->type = elementhash[i]; // find element type
     778              mol->AddAtom(neues);
     779            } else
     780              neues = AtomList[i][j];
     781            status = (status &&
     782                    ParseForParameter(verbose,file, keyword, 0, 1, 1, double_type, &neues->x.x[0], 1, (repetition == 0) ? critical : optional) &&
     783                    ParseForParameter(verbose,file, keyword, 0, 2, 1, double_type, &neues->x.x[1], 1, (repetition == 0) ? critical : optional) &&
     784                    ParseForParameter(verbose,file, keyword, 0, 3, 1, double_type, &neues->x.x[2], 1, (repetition == 0) ? critical : optional) &&
     785                    ParseForParameter(verbose,file, keyword, 0, 4, 1, int_type, &neues->FixedIon, 1, (repetition == 0) ? critical : optional));
     786            if (!status) break;
     787
     788            // check size of vectors
     789            if (mol->Trajectories[neues].R.size() <= (unsigned int)(repetition)) {
     790              //cout << "Increasing size for trajectory array of " << keyword << " to " << (repetition+10) << "." << endl;
     791              mol->Trajectories[neues].R.resize(repetition+10);
     792              mol->Trajectories[neues].U.resize(repetition+10);
     793              mol->Trajectories[neues].F.resize(repetition+10);
     794            }
     795
     796            // put into trajectories list
     797            for (int d=0;d<NDIM;d++)
     798              mol->Trajectories[neues].R.at(repetition).x[d] = neues->x.x[d];
     799
     800            // parse velocities if present
     801            if(!ParseForParameter(verbose,file, keyword, 0, 5, 1, double_type, &neues->v.x[0], 1,optional))
     802              neues->v.x[0] = 0.;
     803            if(!ParseForParameter(verbose,file, keyword, 0, 6, 1, double_type, &neues->v.x[1], 1,optional))
     804              neues->v.x[1] = 0.;
     805            if(!ParseForParameter(verbose,file, keyword, 0, 7, 1, double_type, &neues->v.x[2], 1,optional))
     806              neues->v.x[2] = 0.;
     807            for (int d=0;d<NDIM;d++)
     808              mol->Trajectories[neues].U.at(repetition).x[d] = neues->v.x[d];
     809
     810            // parse forces if present
     811            if(!ParseForParameter(verbose,file, keyword, 0, 8, 1, double_type, &value[0], 1,optional))
     812              value[0] = 0.;
     813            if(!ParseForParameter(verbose,file, keyword, 0, 9, 1, double_type, &value[1], 1,optional))
     814              value[1] = 0.;
     815            if(!ParseForParameter(verbose,file, keyword, 1, 10, 1, double_type, &value[2], 1,optional))
     816              value[2] = 0.;
     817            for (int d=0;d<NDIM;d++)
     818              mol->Trajectories[neues].F.at(repetition).x[d] = value[d];
     819
     820  //            cout << "Parsed position of step " << (repetition) << ": (";
     821  //            for (int d=0;d<NDIM;d++)
     822  //              cout << mol->Trajectories[neues].R.at(repetition).x[d] << " ";          // next step
     823  //            cout << ")\t(";
     824  //            for (int d=0;d<NDIM;d++)
     825  //              cout << mol->Trajectories[neues].U.at(repetition).x[d] << " ";          // next step
     826  //            cout << ")\t(";
     827  //            for (int d=0;d<NDIM;d++)
     828  //              cout << mol->Trajectories[neues].F.at(repetition).x[d] << " ";          // next step
     829  //            cout << ")" << endl;
     830          }
     831        }
     832        repetition++;
     833      }
     834      repetition--;
     835      cout << "Found " << repetition << " trajectory steps." << endl;
     836      mol->MDSteps = repetition;
     837    } else {
     838      // 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)
     839      repetition = 0;
     840      while ( ParseForParameter(verbose,file, "Ion_Type1_1", 0, 1, 1, double_type, &value[0], repetition, (repetition == 0) ? critical : optional) &&
     841              ParseForParameter(verbose,file, "Ion_Type1_1", 0, 2, 1, double_type, &value[1], repetition, (repetition == 0) ? critical : optional) &&
     842              ParseForParameter(verbose,file, "Ion_Type1_1", 0, 3, 1, double_type, &value[2], repetition, (repetition == 0) ? critical : optional))
     843        repetition++;
     844      cout << "I found " << repetition << " times the keyword Ion_Type1_1." << endl;
     845      // parse in molecule coordinates
     846      for (int i=0; i < config::MaxTypes; i++) {
     847        sprintf(name,"Ion_Type%i",i+1);
     848        for(int j=0;j<No[i];j++) {
     849          sprintf(keyword,"%s_%i",name, j+1);
     850          atom *neues = new atom();
     851          // then parse for each atom the coordinates as often as present
     852          ParseForParameter(verbose,file, keyword, 0, 1, 1, double_type, &neues->x.x[0], repetition,critical);
     853          ParseForParameter(verbose,file, keyword, 0, 2, 1, double_type, &neues->x.x[1], repetition,critical);
     854          ParseForParameter(verbose,file, keyword, 0, 3, 1, double_type, &neues->x.x[2], repetition,critical);
     855          ParseForParameter(verbose,file, keyword, 0, 4, 1, int_type, &neues->FixedIon, repetition,critical);
     856          if(!ParseForParameter(verbose,file, keyword, 0, 5, 1, double_type, &neues->v.x[0], repetition,optional))
     857            neues->v.x[0] = 0.;
     858          if(!ParseForParameter(verbose,file, keyword, 0, 6, 1, double_type, &neues->v.x[1], repetition,optional))
     859            neues->v.x[1] = 0.;
     860          if(!ParseForParameter(verbose,file, keyword, 0, 7, 1, double_type, &neues->v.x[2], repetition,optional))
     861            neues->v.x[2] = 0.;
     862          // here we don't care if forces are present (last in trajectories is always equal to current position)
     863          neues->type = elementhash[i]; // find element type
     864          mol->AddAtom(neues);
     865        }
     866      }
     867    }
     868  }
     869  file->close();
     870  delete(file);
    767871};
    768872
     
    774878void config::LoadOld(char *filename, periodentafel *periode, molecule *mol)
    775879{
    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);
     880  ifstream *file = new ifstream(filename);
     881  if (file == NULL) {
     882    cerr << "ERROR: config file " << filename << " missing!" << endl;
     883    return;
     884  }
     885  RetrieveConfigPathAndName(filename);
     886  // ParseParameters
     887
     888  /* Oeffne Hauptparameterdatei */
     889  int l, i, di;
     890  double a,b;
     891  double BoxLength[9];
     892  string zeile;
     893  string dummy;
     894  element *elementhash[128];
     895  int Z, No, AtomNo, found;
     896  int verbose = 0;
     897
     898  /* Namen einlesen */
     899
     900  ParseForParameter(verbose,file, "mainname", 0, 1, 1, string_type, (config::mainname), 1, critical);
     901  ParseForParameter(verbose,file, "defaultpath", 0, 1, 1, string_type, (config::defaultpath), 1, critical);
     902  ParseForParameter(verbose,file, "pseudopotpath", 0, 1, 1, string_type, (config::pseudopotpath), 1, critical);
     903  ParseForParameter(verbose,file, "ProcsGammaPsi", 0, 1, 1, int_type, &(config::ProcPEGamma), 1, critical);
     904  ParseForParameter(verbose,file, "ProcsGammaPsi", 0, 2, 1, int_type, &(config::ProcPEPsi), 1, critical);
     905  config::Seed = 1;
     906  config::DoOutOrbitals = 0;
     907  ParseForParameter(verbose,file,"DoOutVis", 0, 1, 1, int_type, &(config::DoOutVis), 1, critical);
     908  if (config::DoOutVis < 0) config::DoOutVis = 0;
     909  if (config::DoOutVis > 1) config::DoOutVis = 1;
     910  config::VectorPlane = -1;
     911  config::VectorCut = 0.;
     912  ParseForParameter(verbose,file,"DoOutMes", 0, 1, 1, int_type, &(config::DoOutMes), 1, critical);
     913  if (config::DoOutMes < 0) config::DoOutMes = 0;
     914  if (config::DoOutMes > 1) config::DoOutMes = 1;
     915  config::DoOutCurrent = 0;
     916  ParseForParameter(verbose,file,"AddGramSch", 0, 1, 1, int_type, &(config::UseAddGramSch), 1, critical);
     917  if (config::UseAddGramSch < 0) config::UseAddGramSch = 0;
     918  if (config::UseAddGramSch > 2) config::UseAddGramSch = 2;
     919  config::CommonWannier = 0;
     920  config::SawtoothStart = 0.01;
     921
     922  ParseForParameter(verbose,file,"MaxOuterStep", 0, 1, 1, double_type, &(config::MaxOuterStep), 1, critical);
     923  ParseForParameter(verbose,file,"Deltat", 0, 1, 1, double_type, &(config::Deltat), 1, optional);
     924  ParseForParameter(verbose,file,"VisOuterStep", 0, 1, 1, int_type, &(config::OutVisStep), 1, optional);
     925  ParseForParameter(verbose,file,"VisSrcOuterStep", 0, 1, 1, int_type, &(config::OutSrcStep), 1, optional);
     926  ParseForParameter(verbose,file,"TargetTemp", 0, 1, 1, double_type, &(config::TargetTemp), 1, optional);
     927  ParseForParameter(verbose,file,"ScaleTempStep", 0, 1, 1, int_type, &(config::ScaleTempStep), 1, optional);
     928  config::EpsWannier = 1e-8;
     929
     930  // stop conditions
     931  //if (config::MaxOuterStep <= 0) config::MaxOuterStep = 1;
     932  ParseForParameter(verbose,file,"MaxPsiStep", 0, 1, 1, int_type, &(config::MaxPsiStep), 1, critical);
     933  if (config::MaxPsiStep <= 0) config::MaxPsiStep = 3;
     934
     935  ParseForParameter(verbose,file,"MaxMinStep", 0, 1, 1, int_type, &(config::MaxMinStep), 1, critical);
     936  ParseForParameter(verbose,file,"MaxMinStep", 0, 2, 1, double_type, &(config::RelEpsTotalEnergy), 1, critical);
     937  ParseForParameter(verbose,file,"MaxMinStep", 0, 3, 1, double_type, &(config::RelEpsKineticEnergy), 1, critical);
     938  ParseForParameter(verbose,file,"MaxMinStep", 0, 4, 1, int_type, &(config::MaxMinStopStep), 1, critical);
     939  if (config::MaxMinStep <= 0) config::MaxMinStep = config::MaxPsiStep;
     940  if (config::MaxMinStopStep < 1) config::MaxMinStopStep = 1;
     941  config::MaxMinGapStopStep = 1;
     942
     943  ParseForParameter(verbose,file,"MaxInitMinStep", 0, 1, 1, int_type, &(config::MaxInitMinStep), 1, critical);
     944  ParseForParameter(verbose,file,"MaxInitMinStep", 0, 2, 1, double_type, &(config::InitRelEpsTotalEnergy), 1, critical);
     945  ParseForParameter(verbose,file,"MaxInitMinStep", 0, 3, 1, double_type, &(config::InitRelEpsKineticEnergy), 1, critical);
     946  ParseForParameter(verbose,file,"MaxInitMinStep", 0, 4, 1, int_type, &(config::InitMaxMinStopStep), 1, critical);
     947  if (config::MaxInitMinStep <= 0) config::MaxInitMinStep = config::MaxPsiStep;
     948  if (config::InitMaxMinStopStep < 1) config::InitMaxMinStopStep = 1;
     949  config::InitMaxMinGapStopStep = 1;
     950
     951  ParseForParameter(verbose,file, "BoxLength", 0, 3, 3, lower_trigrid, BoxLength, 1, critical); /* Lattice->RealBasis */
     952  mol->cell_size[0] = BoxLength[0];
     953  mol->cell_size[1] = BoxLength[3];
     954  mol->cell_size[2] = BoxLength[4];
     955  mol->cell_size[3] = BoxLength[6];
     956  mol->cell_size[4] = BoxLength[7];
     957  mol->cell_size[5] = BoxLength[8];
     958  if (1) fprintf(stderr,"\n");
     959  config::DoPerturbation = 0;
     960  config::DoFullCurrent = 0;
     961
     962  ParseForParameter(verbose,file,"ECut", 0, 1, 1, double_type, &(config::ECut), 1, critical);
     963  ParseForParameter(verbose,file,"MaxLevel", 0, 1, 1, int_type, &(config::MaxLevel), 1, critical);
     964  ParseForParameter(verbose,file,"Level0Factor", 0, 1, 1, int_type, &(config::Lev0Factor), 1, critical);
     965  if (config::Lev0Factor < 2) {
     966    config::Lev0Factor = 2;
     967  }
     968  ParseForParameter(verbose,file,"RiemannTensor", 0, 1, 1, int_type, &di, 1, critical);
     969  if (di >= 0 && di < 2) {
     970    config::RiemannTensor = di;
     971  } else {
     972    fprintf(stderr, "0 <= RiemanTensor < 2: 0 UseNotRT, 1 UseRT");
     973    exit(1);
     974  }
     975  switch (config::RiemannTensor) {
     976    case 0: //UseNoRT
     977      if (config::MaxLevel < 2) {
     978        config::MaxLevel = 2;
     979      }
     980      config::LevRFactor = 2;
     981      config::RTActualUse = 0;
     982      break;
     983    case 1: // UseRT
     984      if (config::MaxLevel < 3) {
     985        config::MaxLevel = 3;
     986      }
     987      ParseForParameter(verbose,file,"RiemannLevel", 0, 1, 1, int_type, &(config::RiemannLevel), 1, critical);
     988      if (config::RiemannLevel < 2) {
     989        config::RiemannLevel = 2;
     990      }
     991      if (config::RiemannLevel > config::MaxLevel-1) {
     992        config::RiemannLevel = config::MaxLevel-1;
     993      }
     994      ParseForParameter(verbose,file,"LevRFactor", 0, 1, 1, int_type, &(config::LevRFactor), 1, critical);
     995      if (config::LevRFactor < 2) {
     996        config::LevRFactor = 2;
     997      }
     998      config::Lev0Factor = 2;
     999      config::RTActualUse = 2;
     1000      break;
     1001  }
     1002  ParseForParameter(verbose,file,"PsiType", 0, 1, 1, int_type, &di, 1, critical);
     1003  if (di >= 0 && di < 2) {
     1004    config::PsiType = di;
     1005  } else {
     1006    fprintf(stderr, "0 <= PsiType < 2: 0 UseSpinDouble, 1 UseSpinUpDown");
     1007    exit(1);
     1008  }
     1009  switch (config::PsiType) {
     1010  case 0: // SpinDouble
     1011    ParseForParameter(verbose,file,"MaxPsiDouble", 0, 1, 1, int_type, &(config::MaxPsiDouble), 1, critical);
     1012    config::AddPsis = 0;
     1013    break;
     1014  case 1: // SpinUpDown
     1015    if (config::ProcPEGamma % 2) config::ProcPEGamma*=2;
     1016    ParseForParameter(verbose,file,"MaxPsiUp", 0, 1, 1, int_type, &(config::PsiMaxNoUp), 1, critical);
     1017    ParseForParameter(verbose,file,"MaxPsiDown", 0, 1, 1, int_type, &(config::PsiMaxNoDown), 1, critical);
     1018    config::AddPsis = 0;
     1019    break;
     1020  }
     1021
     1022  // IonsInitRead
     1023
     1024  ParseForParameter(verbose,file,"RCut", 0, 1, 1, double_type, &(config::RCut), 1, critical);
     1025  ParseForParameter(verbose,file,"IsAngstroem", 0, 1, 1, int_type, &(config::IsAngstroem), 1, critical);
     1026  config::RelativeCoord = 0;
     1027  config::StructOpt = 0;
     1028
     1029  // Routine from builder.cpp
     1030
     1031
     1032  for (i=MAX_ELEMENTS;i--;)
     1033    elementhash[i] = NULL;
     1034  cout << Verbose(0) << "Parsing Ions ..." << endl;
     1035  No=0;
     1036  found = 0;
     1037  while (getline(*file,zeile,'\n')) {
     1038    if (zeile.find("Ions_Data") == 0) {
     1039      cout << Verbose(1) << "found Ions_Data...begin parsing" << endl;
     1040      found ++;
     1041    }
     1042    if (found > 0) {
     1043      if (zeile.find("Ions_Data") == 0)
     1044        getline(*file,zeile,'\n'); // read next line and parse this one
     1045      istringstream input(zeile);
     1046      input >> AtomNo;  // number of atoms
     1047      input >> Z;      // atomic number
     1048      input >> a;
     1049      input >> l;
     1050      input >> l;
     1051      input >> b;    // element mass
     1052      elementhash[No] = periode->FindElement(Z);
     1053      cout << Verbose(1) << "AtomNo: " << AtomNo << "\tZ: " << Z << "\ta:" << a << "\tl:"  << l << "\b:" << b << "\tElement:" << elementhash[No] << "\t:" << endl;
     1054      for(i=0;i<AtomNo;i++) {
     1055        if (!getline(*file,zeile,'\n')) {// parse on and on
     1056          cout << Verbose(2) << "Error: Too few items in ionic list of element" << elementhash[No] << "." << endl << "Exiting." << endl;
     1057          // return 1;
     1058        } else {
     1059          //cout << Verbose(2) << "Reading line: " << zeile << endl;
     1060        }
     1061        istringstream input2(zeile);
     1062        atom *neues = new atom();
     1063        input2 >> neues->x.x[0]; // x
     1064        input2 >> neues->x.x[1]; // y
     1065        input2 >> neues->x.x[2]; // z
     1066        input2 >> l;
     1067        neues->type = elementhash[No]; // find element type
     1068        mol->AddAtom(neues);
     1069      }
     1070      No++;
     1071    }
     1072  }
     1073  file->close();
     1074  delete(file);
    9711075};
    9721076
     
    9781082bool config::Save(const char *filename, periodentafel *periode, molecule *mol) const
    9791083{
    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;
     1084  bool result = true;
     1085  // bring MaxTypes up to date
     1086  mol->CountElements();
     1087  ofstream *output = NULL;
     1088  output = new ofstream(filename, ios::out);
     1089  if (output != NULL) {
     1090    *output << "# ParallelCarParinello - main configuration file - created with molecuilder" << endl;
     1091    *output << endl;
     1092    *output << "mainname\t" << config::mainname << "\t# programm name (for runtime files)" << endl;
     1093    *output << "defaultpath\t" << config::defaultpath << "\t# where to put files during runtime" << endl;
     1094    *output << "pseudopotpath\t" << config::pseudopotpath << "\t# where to find pseudopotentials" << endl;
     1095    *output << endl;
     1096    *output << "ProcPEGamma\t" << config::ProcPEGamma << "\t# for parallel computing: share constants" << endl;
     1097    *output << "ProcPEPsi\t" << config::ProcPEPsi << "\t# for parallel computing: share wave functions" << endl;
     1098    *output << "DoOutVis\t" << config::DoOutVis << "\t# Output data for OpenDX" << endl;
     1099    *output << "DoOutMes\t" << config::DoOutMes << "\t# Output data for measurements" << endl;
     1100    *output << "DoOutOrbitals\t" << config::DoOutOrbitals << "\t# Output all Orbitals" << endl;
     1101    *output << "DoOutCurr\t" << config::DoOutCurrent << "\t# Ouput current density for OpenDx" << endl;
     1102    *output << "DoOutNICS\t" << config::DoOutNICS << "\t# Output Nucleus independent current shieldings" << endl;
     1103    *output << "DoPerturbation\t" << config::DoPerturbation << "\t# Do perturbation calculate and determine susceptibility and shielding" << endl;
     1104    *output << "DoFullCurrent\t" << config::DoFullCurrent << "\t# Do full perturbation" << endl;
     1105    *output << "DoConstrainedMD\t" << config::DoConstrainedMD << "\t# Do perform a constrained (>0, relating to current MD step) instead of unconstrained (0) MD" << endl;
     1106    *output << "Thermostat\t" << ThermostatNames[Thermostat] << "\t";
     1107    switch(Thermostat) {
     1108      default:
     1109      case None:
     1110        break;
     1111      case Woodcock:
     1112        *output << ScaleTempStep;
     1113        break;
     1114      case Gaussian:
     1115        *output << ScaleTempStep;
     1116        break;
     1117      case Langevin:
     1118        *output << TempFrequency << "\t" << alpha;
     1119        break;
     1120      case Berendsen:
     1121        *output << TempFrequency;
     1122        break;
     1123      case NoseHoover:
     1124        *output << HooverMass;
     1125        break;
     1126    };
     1127    *output << "\t# Which Thermostat and its parameters to use in MD case." << endl;
     1128    *output << "CommonWannier\t" << config::CommonWannier << "\t# Put virtual centers at indivual orbits, all common, merged by variance, to grid point, to cell center" << endl;
     1129    *output << "SawtoothStart\t" << config::SawtoothStart << "\t# Absolute value for smooth transition at cell border " << endl;
     1130    *output << "VectorPlane\t" << config::VectorPlane << "\t# Cut plane axis (x, y or z: 0,1,2) for two-dim current vector plot" << endl;
     1131    *output << "VectorCut\t" << config::VectorCut << "\t# Cut plane axis value" << endl;
     1132    *output << "AddGramSch\t" << config::UseAddGramSch << "\t# Additional GramSchmidtOrtogonalization to be safe" << endl;
     1133    *output << "Seed\t\t" << config::Seed << "\t# initial value for random seed for Psi coefficients" << endl;
     1134    *output << endl;
     1135    *output << "MaxOuterStep\t" << config::MaxOuterStep << "\t# number of MolecularDynamics/Structure optimization steps" << endl;
     1136    *output << "Deltat\t" << config::Deltat << "\t# time per MD step" << endl;
     1137    *output << "OutVisStep\t" << config::OutVisStep << "\t# Output visual data every ...th step" << endl;
     1138    *output << "OutSrcStep\t" << config::OutSrcStep << "\t# Output \"restart\" data every ..th step" << endl;
     1139    *output << "TargetTemp\t" << config::TargetTemp << "\t# Target temperature" << endl;
     1140    *output << "MaxPsiStep\t" << config::MaxPsiStep << "\t# number of Minimisation steps per state (0 - default)" << endl;
     1141    *output << "EpsWannier\t" << config::EpsWannier << "\t# tolerance value for spread minimisation of orbitals" << endl;
     1142    *output << endl;
     1143    *output << "# Values specifying when to stop" << endl;
     1144    *output << "MaxMinStep\t" << config::MaxMinStep << "\t# Maximum number of steps" << endl;
     1145    *output << "RelEpsTotalE\t" << config::RelEpsTotalEnergy << "\t# relative change in total energy" << endl;
     1146    *output << "RelEpsKineticE\t" << config::RelEpsKineticEnergy << "\t# relative change in kinetic energy" << endl;
     1147    *output << "MaxMinStopStep\t" << config::MaxMinStopStep << "\t# check every ..th steps" << endl;
     1148    *output << "MaxMinGapStopStep\t" << config::MaxMinGapStopStep << "\t# check every ..th steps" << endl;
     1149    *output << endl;
     1150    *output << "# Values specifying when to stop for INIT, otherwise same as above" << endl;
     1151    *output << "MaxInitMinStep\t" << config::MaxInitMinStep << "\t# Maximum number of steps" << endl;
     1152    *output << "InitRelEpsTotalE\t" << config::InitRelEpsTotalEnergy << "\t# relative change in total energy" << endl;
     1153    *output << "InitRelEpsKineticE\t" << config::InitRelEpsKineticEnergy << "\t# relative change in kinetic energy" << endl;
     1154    *output << "InitMaxMinStopStep\t" << config::InitMaxMinStopStep << "\t# check every ..th steps" << endl;
     1155    *output << "InitMaxMinGapStopStep\t" << config::InitMaxMinGapStopStep << "\t# check every ..th steps" << endl;
     1156    *output << endl;
     1157    *output << "BoxLength\t\t\t# (Length of a unit cell)" << endl;
     1158    *output << mol->cell_size[0] << "\t" << endl;
     1159    *output << mol->cell_size[1] << "\t" << mol->cell_size[2] << "\t" << endl;
     1160    *output << mol->cell_size[3] << "\t" << mol->cell_size[4] << "\t" << mol->cell_size[5] << "\t" << endl;
     1161    // FIXME
     1162    *output << endl;
     1163    *output << "ECut\t\t" << config::ECut << "\t# energy cutoff for discretization in Hartrees" << endl;
     1164    *output << "MaxLevel\t" << config::MaxLevel << "\t# number of different levels in the code, >=2" << endl;
     1165    *output << "Level0Factor\t" << config::Lev0Factor << "\t# factor by which node number increases from S to 0 level" << endl;
     1166    *output << "RiemannTensor\t" << config::RiemannTensor << "\t# (Use metric)" << endl;
     1167    switch (config::RiemannTensor) {
     1168      case 0: //UseNoRT
     1169        break;
     1170      case 1: // UseRT
     1171        *output << "RiemannLevel\t" << config::RiemannLevel << "\t# Number of Riemann Levels" << endl;
     1172        *output << "LevRFactor\t" << config::LevRFactor << "\t# factor by which node number increases from 0 to R level from" << endl;
     1173        break;
     1174    }
     1175    *output << "PsiType\t\t" << config::PsiType << "\t# 0 - doubly occupied, 1 - SpinUp,SpinDown" << endl;
     1176    // write out both types for easier changing afterwards
     1177  //  switch (PsiType) {
     1178  //    case 0:
     1179        *output << "MaxPsiDouble\t" << config::MaxPsiDouble << "\t# here: specifying both maximum number of SpinUp- and -Down-states" << endl;
     1180  //      break;
     1181  //    case 1:
     1182        *output << "PsiMaxNoUp\t" << config::PsiMaxNoUp << "\t# here: specifying maximum number of SpinUp-states" << endl;
     1183        *output << "PsiMaxNoDown\t" << config::PsiMaxNoDown << "\t# here: specifying maximum number of SpinDown-states" << endl;
     1184  //      break;
     1185  //  }
     1186    *output << "AddPsis\t\t" << config::AddPsis << "\t# Additional unoccupied Psis for bandgap determination" << endl;
     1187    *output << endl;
     1188    *output << "RCut\t\t" << config::RCut << "\t# R-cut for the ewald summation" << endl;
     1189    *output << "StructOpt\t" << config::StructOpt << "\t# Do structure optimization beforehand" << endl;
     1190    *output << "IsAngstroem\t" << config::IsAngstroem << "\t# 0 - Bohr, 1 - Angstroem" << endl;
     1191    *output << "RelativeCoord\t" << config::RelativeCoord << "\t# whether ion coordinates are relative (1) or absolute (0)" << endl;
     1192    *output << "MaxTypes\t" << mol->ElementCount <<  "\t# maximum number of different ion types" << endl;
     1193    *output << endl;
     1194    result = result && mol->Checkout(output);
     1195    if (mol->MDSteps <=1 )
     1196      result = result && mol->Output(output);
     1197    else
     1198      result = result && mol->OutputTrajectories(output);
     1199    output->close();
     1200    output->clear();
     1201    delete(output);
     1202    return result;
     1203  } else
     1204    return false;
    10781205};
    10791206
     
    10851212bool config::SaveMPQC(const char *filename, molecule *mol) const
    10861213{
    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;
     1214  int ElementNo = 0;
     1215  int AtomNo;
     1216  atom *Walker = NULL;
     1217  element *runner = NULL;
     1218  Vector *center = NULL;
     1219  ofstream *output = NULL;
     1220  stringstream *fname = NULL;
     1221
     1222  // first without hessian
     1223  fname = new stringstream;
     1224  *fname << filename << ".in";
     1225  output = new ofstream(fname->str().c_str(), ios::out);
     1226  *output << "% Created by MoleCuilder" << endl;
     1227  *output << "mpqc: (" << endl;
     1228  *output << "\tsavestate = no" << endl;
     1229  *output << "\tdo_gradient = yes" << endl;
     1230  *output << "\tmole<MBPT2>: (" << endl;
     1231  *output << "\t\tmaxiter = 200" << endl;
     1232  *output << "\t\tbasis = $:basis" << endl;
     1233  *output << "\t\tmolecule = $:molecule" << endl;
     1234  *output << "\t\treference<CLHF>: (" << endl;
     1235  *output << "\t\t\tbasis = $:basis" << endl;
     1236  *output << "\t\t\tmolecule = $:molecule" << endl;
     1237  *output << "\t\t)" << endl;
     1238  *output << "\t)" << endl;
     1239  *output << ")" << endl;
     1240  *output << "molecule<Molecule>: (" << endl;
     1241  *output << "\tunit = " << (IsAngstroem ? "angstrom" : "bohr" ) << endl;
     1242  *output << "\t{ atoms geometry } = {" << endl;
     1243  center = mol->DetermineCenterOfAll(output);
     1244  // output of atoms
     1245  runner = mol->elemente->start;
     1246  while (runner->next != mol->elemente->end) { // go through every element
     1247    runner = runner->next;
     1248    if (mol->ElementsInMolecule[runner->Z]) { // if this element got atoms
     1249      ElementNo++;
     1250      AtomNo = 0;
     1251      Walker = mol->start;
     1252      while (Walker->next != mol->end) { // go through every atom of this element
     1253        Walker = Walker->next;
     1254        if (Walker->type == runner) { // if this atom fits to element
     1255          AtomNo++;
     1256          *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;
     1257        }
     1258      }
     1259    }
     1260  }
     1261  delete(center);
     1262  *output << "\t}" << endl;
     1263  *output << ")" << endl;
     1264  *output << "basis<GaussianBasisSet>: (" << endl;
     1265  *output << "\tname = \"" << basis << "\"" << endl;
     1266  *output << "\tmolecule = $:molecule" << endl;
     1267  *output << ")" << endl;
     1268  output->close();
     1269  delete(output);
     1270  delete(fname);
     1271
     1272  // second with hessian
     1273  fname = new stringstream;
     1274  *fname << filename << ".hess.in";
     1275  output = new ofstream(fname->str().c_str(), ios::out);
     1276  *output << "% Created by MoleCuilder" << endl;
     1277  *output << "mpqc: (" << endl;
     1278  *output << "\tsavestate = no" << endl;
     1279  *output << "\tdo_gradient = yes" << endl;
     1280  *output << "\tmole<CLHF>: (" << endl;
     1281  *output << "\t\tmaxiter = 200" << endl;
     1282  *output << "\t\tbasis = $:basis" << endl;
     1283  *output << "\t\tmolecule = $:molecule" << endl;
     1284  *output << "\t)" << endl;
     1285  *output << "\tfreq<MolecularFrequencies>: (" << endl;
     1286  *output << "\t\tmolecule=$:molecule" << endl;
     1287  *output << "\t)" << endl;
     1288  *output << ")" << endl;
     1289  *output << "molecule<Molecule>: (" << endl;
     1290  *output << "\tunit = " << (IsAngstroem ? "angstrom" : "bohr" ) << endl;
     1291  *output << "\t{ atoms geometry } = {" << endl;
     1292  center = mol->DetermineCenterOfAll(output);
     1293  // output of atoms
     1294  runner = mol->elemente->start;
     1295  while (runner->next != mol->elemente->end) { // go through every element
     1296    runner = runner->next;
     1297    if (mol->ElementsInMolecule[runner->Z]) { // if this element got atoms
     1298      ElementNo++;
     1299      AtomNo = 0;
     1300      Walker = mol->start;
     1301      while (Walker->next != mol->end) { // go through every atom of this element
     1302        Walker = Walker->next;
     1303        if (Walker->type == runner) { // if this atom fits to element
     1304          AtomNo++;
     1305          *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;
     1306        }
     1307      }
     1308    }
     1309  }
     1310  delete(center);
     1311  *output << "\t}" << endl;
     1312  *output << ")" << endl;
     1313  *output << "basis<GaussianBasisSet>: (" << endl;
     1314  *output << "\tname = \"3-21G\"" << endl;
     1315  *output << "\tmolecule = $:molecule" << endl;
     1316  *output << ")" << endl;
     1317  output->close();
     1318  delete(output);
     1319  delete(fname);
     1320
     1321  return true;
    11951322};
    11961323
     
    12041331 * \param name Name of value in file (at least 3 chars!)
    12051332 * \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!)
     1333 *        (if file is sequentially parsed this can be way faster! However, beware of multiple values per line, as whole line is read -
     1334 *        best approach: 0 0 0 1 (not resetted only on last value of line) - and of yth, which is now
     1335 *        counted from this unresetted position!)
    12091336 * \param xth Which among a number of parameters it is (in grid case it's row number as grid is read as a whole!)
    12101337 * \param yth In grid case specifying column number, otherwise the yth \a name matching line
     
    12171344 */
    12181345int 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
     1346  int i,j;  // loop variables
     1347  int length = 0, maxlength = -1;
     1348  long file_position = file->tellg(); // mark current position
     1349  char *dummy1, *dummy, *free_dummy;    // pointers in the line that is read in per step
     1350  dummy1 = free_dummy = (char *) Malloc(256 * sizeof(char), "config::ParseForParameter: *free_dummy");
     1351
     1352  //fprintf(stderr,"Parsing for %s\n",name);
     1353  if (repetition == 0)
     1354    //Error(SomeError, "ParseForParameter(): argument repetition must not be 0!");
     1355    return 0;
     1356
     1357  int line = 0; // marks line where parameter was found
     1358  int found = (type >= grid) ? 0 : (-yth + 1);  // marks if yth parameter name was found
     1359  while((found != repetition)) {
     1360    dummy1 = dummy = free_dummy;
     1361    do {
     1362      file->getline(dummy1, 256); // Read the whole line
     1363      if (file->eof()) {
     1364        if ((critical) && (found == 0)) {
     1365          Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
     1366          //Error(InitReading, name);
     1367          fprintf(stderr,"Error:InitReading, critical %s not found\n", name);
     1368          exit(255);
     1369        } else {
     1370          //if (!sequential)
     1371          file->clear();
     1372          file->seekg(file_position, ios::beg);  // rewind to start position
     1373          Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
     1374          return 0;
     1375        }
     1376      }
     1377      line++;
     1378    } while (dummy != NULL && dummy1 != NULL && ((dummy1[0] == '#') || (dummy1[0] == '\0'))); // skip commentary and empty lines
     1379
     1380    // C++ getline removes newline at end, thus re-add
     1381    if ((dummy1 != NULL) && (strchr(dummy1,'\n') == NULL)) {
     1382      i = strlen(dummy1);
     1383      dummy1[i] = '\n';
     1384      dummy1[i+1] = '\0';
     1385    }
     1386    //fprintf(stderr,"line %i ends at %i, newline at %i\n", line, strlen(dummy1), strchr(dummy1,'\n')-free_dummy);
     1387
     1388    if (dummy1 == NULL) {
     1389      if (verbose) fprintf(stderr,"Error reading line %i\n",line);
     1390    } else {
     1391      //fprintf(stderr,"Now parsing the line %i: %s\n", line, dummy1);
     1392    }
     1393    // Seek for possible end of keyword on line if given ...
     1394    if (name != NULL) {
     1395      dummy = strchr(dummy1,'\t');  // set dummy on first tab or space which ever's nearer
     1396      if (dummy == NULL) {
     1397        dummy = strchr(dummy1, ' ');  // if not found seek for space
     1398        while ((dummy != NULL) && ((*dummy == '\t') || (*dummy == ' ')))    // skip some more tabs and spaces if necessary
     1399          dummy++;
     1400      }
     1401      if (dummy == NULL) {
     1402        dummy = strchr(dummy1, '\n'); // set on line end then (whole line = keyword)
     1403        //fprintf(stderr,"Error: Cannot find tabs or spaces on line %i in search for %s\n", line, name);
     1404        //Free((void **)&free_dummy);
     1405        //Error(FileOpenParams, NULL);
     1406      } else {
     1407        //fprintf(stderr,"found tab at %i\n",(char *)dummy-(char *)dummy1);
     1408      }
     1409    } else dummy = dummy1;
     1410    // ... and check if it is the keyword!
     1411    //fprintf(stderr,"name %p, dummy %i/%c, dummy1 %i/%c, strlen(name) %i\n", &name, dummy, *dummy, dummy1, *dummy1, strlen(name));
     1412    if ((name == NULL) || (((dummy-dummy1 >= 3) && (strncmp(dummy1, name, strlen(name)) == 0)) && ((unsigned int)(dummy-dummy1) == strlen(name)))) {
     1413      found++; // found the parameter!
     1414      //fprintf(stderr,"found %s at line %i between %i and %i\n", name, line, dummy1, dummy);
     1415
     1416      if (found == repetition) {
     1417        for (i=0;i<xth;i++) { // i = rows
     1418          if (type >= grid) {
     1419            // grid structure means that grid starts on the next line, not right after keyword
     1420            dummy1 = dummy = free_dummy;
     1421            do {
     1422              file->getline(dummy1, 256); // Read the whole line, skip commentary and empty ones
     1423              if (file->eof()) {
     1424                if ((critical) && (found == 0)) {
     1425                  Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
     1426                  //Error(InitReading, name);
     1427                  fprintf(stderr,"Error:InitReading, critical %s not found\n", name);
     1428                  exit(255);
     1429                } else {
     1430                  //if (!sequential)
     1431                  file->clear();
     1432                  file->seekg(file_position, ios::beg);  // rewind to start position
     1433                  Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
     1434                  return 0;
     1435                }
     1436              }
     1437              line++;
     1438            } while ((dummy1[0] == '#') || (dummy1[0] == '\n'));
     1439            if (dummy1 == NULL){
     1440              if (verbose) fprintf(stderr,"Error reading line %i\n", line);
     1441            } else {
     1442              //fprintf(stderr,"Reading next line %i: %s\n", line, dummy1);
     1443            }
     1444          } else { // simple int, strings or doubles start in the same line
     1445            while ((*dummy == '\t') || (*dummy == ' '))  // skip interjacent tabs and spaces
     1446              dummy++;
     1447          }
     1448          // C++ getline removes newline at end, thus re-add
     1449          if ((dummy1 != NULL) && (strchr(dummy1,'\n') == NULL)) {
     1450            j = strlen(dummy1);
     1451            dummy1[j] = '\n';
     1452            dummy1[j+1] = '\0';
     1453          }
     1454
     1455          int start = (type >= grid) ? 0 : yth-1 ;
     1456          for (j=start;j<yth;j++) { // j = columns
     1457            // check for lower triangular area and upper triangular area
     1458            if ( ((i > j) && (type == upper_trigrid)) || ((j > i) && (type == lower_trigrid))) {
     1459              *((double *)value) = 0.0;
     1460              fprintf(stderr,"%f\t",*((double *)value));
     1461              value = (void *)((long)value + sizeof(double));
     1462              //value += sizeof(double);
     1463            } else {
     1464              // otherwise we must skip all interjacent tabs and spaces and find next value
     1465              dummy1 = dummy;
     1466              dummy = strchr(dummy1, '\t'); // seek for tab or space
     1467              if (dummy == NULL)
     1468                dummy = strchr(dummy1, ' ');  // if not found seek for space
     1469              if (dummy == NULL) { // if still zero returned ...
     1470                dummy = strchr(dummy1, '\n');  // ... at line end then
     1471                if ((j < yth-1) && (type < 4)) {  // check if xth value or not yet
     1472                  if (critical) {
     1473                    if (verbose) fprintf(stderr,"Error: EoL at %i and still missing %i value(s) for parameter %s\n", line, yth-j, name);
     1474                    Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
     1475                    //return 0;
     1476                    exit(255);
     1477                    //Error(FileOpenParams, NULL);
     1478                  } else {
     1479                    //if (!sequential)
     1480                    file->clear();
     1481                    file->seekg(file_position, ios::beg);  // rewind to start position
     1482                    Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
     1483                    return 0;
     1484                  }
     1485                }
     1486              } else {
     1487                //fprintf(stderr,"found tab at %i\n",(char *)dummy-(char *)free_dummy);
     1488              }
     1489              if (*dummy1 == '#') {
     1490                // found comment, skipping rest of line
     1491                //if (verbose) fprintf(stderr,"Error: '#' at %i and still missing %i value(s) for parameter %s\n", line, yth-j, name);
     1492                if (!sequential) { // here we need it!
     1493                  file->seekg(file_position, ios::beg);  // rewind to start position
     1494                }
     1495                Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
     1496                return 0;
     1497              }
     1498              //fprintf(stderr,"value from %i to %i\n",(char *)dummy1-(char *)free_dummy,(char *)dummy-(char *)free_dummy);
     1499              switch(type) {
     1500                case (row_int):
     1501                  *((int *)value) = atoi(dummy1);
     1502                  if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name);
     1503                  if (verbose) fprintf(stderr,"%i\t",*((int *)value));
     1504                    value = (void *)((long)value + sizeof(int));
     1505                    //value += sizeof(int);
     1506                  break;
     1507                case(row_double):
     1508                case(grid):
     1509                case(lower_trigrid):
     1510                case(upper_trigrid):
     1511                  *((double *)value) = atof(dummy1);
     1512                  if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name);
     1513                  if (verbose) fprintf(stderr,"%lg\t",*((double *)value));
     1514                  value = (void *)((long)value + sizeof(double));
     1515                  //value += sizeof(double);
     1516                  break;
     1517                case(double_type):
     1518                  *((double *)value) = atof(dummy1);
     1519                  if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %lg\n", name, *((double *) value));
     1520                  //value += sizeof(double);
     1521                  break;
     1522                case(int_type):
     1523                  *((int *)value) = atoi(dummy1);
     1524                  if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %i\n", name, *((int *) value));
     1525                  //value += sizeof(int);
     1526                  break;
     1527                default:
     1528                case(string_type):
     1529                  if (value != NULL) {
     1530                    //if (maxlength == -1) maxlength = strlen((char *)value); // get maximum size of string array
     1531                    maxlength = MAXSTRINGSIZE;
     1532                    length = maxlength > (dummy-dummy1) ? (dummy-dummy1) : maxlength; // cap at maximum
     1533                    strncpy((char *)value, dummy1, length);  // copy as much
     1534                    ((char *)value)[length] = '\0';  // and set end marker
     1535                    if ((verbose) && (i == xth-1)) fprintf(stderr,"%s is '%s' (%i chars)\n",name,((char *) value), length);
     1536                    //value += sizeof(char);
     1537                  } else {
     1538                  }
     1539                break;
     1540              }
     1541            }
     1542            while (*dummy == '\t')
     1543              dummy++;
     1544          }
     1545        }
     1546      }
     1547    }
     1548  }
     1549  if ((type >= row_int) && (verbose)) fprintf(stderr,"\n");
     1550  Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");
     1551  if (!sequential) {
     1552    file->clear();
     1553    file->seekg(file_position, ios::beg);  // rewind to start position
     1554  }
     1555  //fprintf(stderr, "End of Parsing\n\n");
     1556
     1557  return (found); // true if found, false if not
    14311558}
  • src/datacreator.cpp

    r375b458 r51c910  
    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[Fragments.MatrixCounter] << 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[ KeySet.OrderSet[BondOrder][i] ];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[Fragments.MatrixCounter];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[Fragments.MatrixCounter] << 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[ KeySet.OrderSet[BondOrder][i] ];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[Energy.MatrixCounter];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[Fragments.MatrixCounter] << 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[Fragments.MatrixCounter];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[Fragments.MatrixCounter] << 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[Fragments.MatrixCounter];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[Fragments.MatrixCounter] << 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[ Fragments.MatrixCounter ];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[Fragments.MatrixCounter] << 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[ Fragments.MatrixCounter ];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;
     262};
     263
     264
     265/** Plot hessian error vs. vs atom vs. order.
     266 * \param &Hessian HessianMatrix containing reference values (in MatrixCounter matrix)
     267 * \param &Fragments HessianMatrix class containing matrix values
     268 * \param KeySet KeySetContainer class holding bond KeySetContainer::Order
     269 * \param *prefix prefix in filename (without ending)
     270 * \param *msg message to be place in first line as a comment
     271 * \param *datum current date and time
     272 * \return true if file was written successfully
     273 */
     274bool CreateDataDeltaHessianOrderPerAtom(class HessianMatrix &Hessian, class HessianMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum)
     275{
     276  stringstream filename;
     277  ofstream output;
     278
     279  filename << prefix << ".dat";
     280  if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
     281  cout << msg << endl;
     282  output << "# " << msg << ", created on " << datum;
     283  output << "# AtomNo\t" << Fragments.Header[Fragments.MatrixCounter] << endl;
     284  Fragments.SetLastMatrix(Hessian.Matrix[Hessian.MatrixCounter], 0);
     285  for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     286    //cout << "Current order is " << BondOrder << "." << endl;
     287    Fragments.SumSubHessians(Fragments, KeySet, BondOrder, -1.);
     288    // errors per atom
     289    output << endl << "#Order\t" << BondOrder+1 << endl;
     290    for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) {
     291      output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t";
     292      for (int l=0;l<Fragments.ColumnCounter[ Fragments.MatrixCounter ];l++) {
     293        output << scientific << Fragments.Matrix[Fragments.MatrixCounter][ j ][l] << "\t";
     294      }
     295      output << endl;
     296    }
     297    output << endl;
     298  }
     299  output.close();
     300  return true;
     301};
     302
     303/** Plot hessian error vs. vs atom vs. order in the frobenius norm.
     304 * \param &Hessian HessianMatrix containing reference values (in MatrixCounter matrix)
     305 * \param &Fragments HessianMatrix class containing matrix values
     306 * \param KeySet KeySetContainer class holding bond KeySetContainer::Order
     307 * \param *prefix prefix in filename (without ending)
     308 * \param *msg message to be place in first line as a comment
     309 * \param *datum current date and time
     310 * \return true if file was written successfully
     311 */
     312bool CreateDataDeltaFrobeniusOrderPerAtom(class HessianMatrix &Hessian, class HessianMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum)
     313{
     314  stringstream filename;
     315  ofstream output;
     316  double norm = 0;
     317  double tmp;
     318
     319  filename << prefix << ".dat";
     320  if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
     321  cout << msg << endl;
     322  output << "# " << msg << ", created on " << datum;
     323  output << "# AtomNo\t";
     324  Fragments.SetLastMatrix(Hessian.Matrix[Hessian.MatrixCounter], 0);
     325  for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     326    output << "Order" << BondOrder+1 << "\t";
     327  }
     328  output << endl;
     329  output << Fragments.RowCounter[ Fragments.MatrixCounter ] << "\t";
     330  for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     331    //cout << "Current order is " << BondOrder << "." << endl;
     332    Fragments.SumSubHessians(Fragments, KeySet, BondOrder, -1.);
     333    // frobenius norm of errors per atom
     334    norm = 0.;
     335    for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) {
     336      for (int l=0;l<Fragments.ColumnCounter[ Fragments.MatrixCounter ];l++) {
     337        tmp = Fragments.Matrix[Fragments.MatrixCounter][ j ][l];
     338        norm += tmp*tmp;
     339      }
     340    }
     341    output << scientific << sqrt(norm)/(Fragments.RowCounter[ Fragments.MatrixCounter ]*Fragments.ColumnCounter[ Fragments.MatrixCounter] ) << "\t";
     342  }
     343  output << endl;
     344  output.close();
     345  return true;
     346};
     347
     348/** Plot hessian error vs. vs atom vs. order.
     349 * \param &Fragments HessianMatrix class containing matrix values
     350 * \param KeySet KeySetContainer class holding bond KeySetContainer::Order
     351 * \param *prefix prefix in filename (without ending)
     352 * \param *msg message to be place in first line as a comment
     353 * \param *datum current date and time
     354 * \return true if file was written successfully
     355 */
     356bool CreateDataHessianOrderPerAtom(class HessianMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum)
     357{
     358  stringstream filename;
     359  ofstream output;
     360
     361  filename << prefix << ".dat";
     362  if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
     363  cout << msg << endl;
     364  output << "# " << msg << ", created on " << datum;
     365  output << "# AtomNo\t" << Fragments.Header[ Fragments.MatrixCounter ] << endl;
     366  Fragments.SetLastMatrix(0., 0);
     367  for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     368    //cout << "Current order is " << BondOrder << "." << endl;
     369    Fragments.SumSubHessians(Fragments, KeySet, BondOrder, 1.);
     370    // errors per atom
     371    output << endl << "#Order\t" << BondOrder+1 << endl;
     372    for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) {
     373      output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t";
     374      for (int l=0;l<Fragments.ColumnCounter[ Fragments.MatrixCounter ];l++)
     375        output << scientific << Fragments.Matrix[Fragments.MatrixCounter][ j ][l] << "\t";
     376      output << endl;
     377    }
     378    output << endl;
     379  }
     380  output.close();
     381  return true;
    262382};
    263383
     
    266386bool CreateDataFragment(class MatrixContainer &Fragment, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateFragment)(class MatrixContainer &, int))
    267387{
    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;
     388  stringstream filename;
     389  ofstream output;
     390
     391  filename << prefix << ".dat";
     392  if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
     393  cout << msg << endl;
     394  output << "# " << msg << ", created on " << datum << endl;
     395  output << "#Order\tFrag.No.\t" << Fragment.Header[ Fragment.MatrixCounter ] << endl;
     396  for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     397    for(int i=0;i<KeySet.FragmentsPerOrder[BondOrder];i++) {
     398      output << BondOrder+1 << "\t" << KeySet.OrderSet[BondOrder][i]+1;
     399      CreateFragment(Fragment, KeySet.OrderSet[BondOrder][i]);
     400      for (int l=0;l<Fragment.ColumnCounter[ KeySet.OrderSet[BondOrder][i] ];l++)
     401        output << scientific << "\t" << Fragment.Matrix[ KeySet.OrderSet[BondOrder][i] ][ Fragment.RowCounter[ KeySet.OrderSet[BondOrder][i] ] ][l];
     402      output << endl;
     403    }
     404  }
     405  output.close();
     406  return true;
    287407};
    288408
     
    294414void CreateMaxFragmentOrder(class MatrixContainer &Fragments, class KeySetsContainer &KeySet, int BondOrder)
    295415{
    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         }
     416  for(int j=Fragments.RowCounter[ Fragments.MatrixCounter ];j--;) {
     417    for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) {
     418      if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) < fabs(Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][1])) {
     419        for (int k=Fragments.ColumnCounter[ Fragments.MatrixCounter ];k--;)
     420          Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
     421      }
     422    }
     423  }
    304424};
    305425
     
    311431void CreateMinFragmentOrder(class MatrixContainer &Fragments, class KeySetsContainer &KeySet, int BondOrder)
    312432{
    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         }
     433  for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) {
     434    int i=0;
     435    do {  // first get a minimum value unequal to 0
     436      for (int k=Fragments.ColumnCounter[ Fragments.MatrixCounter ];k--;)
     437        Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
     438      i++;
     439    } while ((fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) < MYEPSILON) && (i<KeySet.FragmentsPerOrder[BondOrder]));
     440    for(;i<KeySet.FragmentsPerOrder[BondOrder];i++) { // then find lowest
     441      if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) > fabs(Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][1])) {
     442        for (int k=Fragments.ColumnCounter[ Fragments.MatrixCounter ];k--;)
     443          Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
     444      }
     445    }
     446  }
    327447};
    328448
     
    331451bool CreateDataFragmentOrder(class MatrixContainer &Fragment, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateFragmentOrder)(class MatrixContainer &, class KeySetsContainer &, int))
    332452{
    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;
     453  stringstream filename;
     454  ofstream output;
     455
     456  filename << prefix << ".dat";
     457  if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
     458  cout << msg << endl;
     459  output << "# " << msg << ", created on " << datum;
     460  output << "#Order\tFrag.No.\t" << Fragment.Header[ Fragment.MatrixCounter ] << endl;
     461  // max
     462  for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     463    Fragment.SetLastMatrix(0.,0);
     464    CreateFragmentOrder(Fragment, KeySet, BondOrder);
     465    output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder];
     466    for (int l=0;l<Fragment.ColumnCounter[ Fragment.MatrixCounter ];l++)
     467      output << scientific << "\t" << Fragment.Matrix[ Fragment.MatrixCounter ][ Fragment.RowCounter[ Fragment.MatrixCounter ]-1 ][l];
     468    output << endl;
     469  }
     470  output.close();
     471  return true;
    352472};
    353473
     
    358478void CreateEnergy(class MatrixContainer &Energy, int MatrixNumber)
    359479{
    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];
     480  for(int k=0;k<Energy.ColumnCounter[MatrixNumber];k++)
     481    Energy.Matrix[MatrixNumber][ Energy.RowCounter[MatrixNumber] ] [k] =  Energy.Matrix[MatrixNumber][ Energy.RowCounter[MatrixNumber]-1 ] [k];
    362482};
    363483
     
    369489void CreateMinimumForce(class MatrixContainer &Force, int MatrixNumber)
    370490{
    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         }
     491  for (int l=Force.ColumnCounter[MatrixNumber];l--;)
     492    Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.;
     493  for (int l=5;l<Force.ColumnCounter[MatrixNumber];l+=3) {
     494    double stored = 0;
     495    int k=0;
     496    do {
     497      for (int m=NDIM;m--;) {
     498        stored += Force.Matrix[MatrixNumber][ k ][l+m]
     499              * Force.Matrix[MatrixNumber][ k ][l+m];
     500        Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m]  = Force.Matrix[MatrixNumber][ k ][l+m];
     501      }
     502      k++;
     503    } while ((fabs(stored) < MYEPSILON) && (k<Force.RowCounter[MatrixNumber]));
     504    for (;k<Force.RowCounter[MatrixNumber];k++) {
     505      double tmp = 0;
     506      for (int m=NDIM;m--;)
     507        tmp += Force.Matrix[MatrixNumber][ k ][l+m]
     508              * Force.Matrix[MatrixNumber][ k ][l+m];
     509      if ((fabs(tmp) > MYEPSILON) && (tmp < stored)) {  // current force is greater than stored
     510        for (int m=NDIM;m--;)
     511          Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m]  = Force.Matrix[MatrixNumber][ k ][l+m];
     512        stored = tmp;
     513      }
     514    }
     515  }
    396516};
    397517
     
    399519 * Results are stored in the matrix ForceMatrix::MatrixCounter of \a Force.
    400520 * \param Force ForceMatrix class containing matrix values
    401         * \param MatrixNumber the index for the ForceMatrix::matrix array
     521  * \param MatrixNumber the index for the ForceMatrix::matrix array
    402522 */
    403523void CreateMeanForce(class MatrixContainer &Force, int MatrixNumber)
    404524{
    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         }
     525  int divisor = 0;
     526  for (int l=Force.ColumnCounter[MatrixNumber];l--;)
     527    Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.;
     528  for (int l=5;l<Force.ColumnCounter[MatrixNumber];l+=3) {
     529    double tmp = 0;
     530    for (int k=Force.RowCounter[MatrixNumber];k--;) {
     531      double norm = 0.;
     532      for (int m=NDIM;m--;)
     533        norm += Force.Matrix[MatrixNumber][ k ][l+m]
     534              * Force.Matrix[MatrixNumber][ k ][l+m];
     535      tmp += sqrt(norm);
     536      if (fabs(norm) > MYEPSILON) divisor++;
     537    }
     538    tmp /= (double)divisor;
     539    Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = tmp;
     540  }
    421541};
    422542
     
    428548void CreateMaximumForce(class MatrixContainer &Force, int MatrixNumber)
    429549{
    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         }
     550  for (int l=5;l<Force.ColumnCounter[MatrixNumber];l+=3) {
     551    double stored = 0;
     552    for (int k=Force.RowCounter[MatrixNumber];k--;) {
     553      double tmp = 0;
     554      for (int m=NDIM;m--;)
     555        tmp += Force.Matrix[MatrixNumber][ k ][l+m]
     556              * Force.Matrix[MatrixNumber][ k ][l+m];
     557      if (tmp > stored) {  // current force is greater than stored
     558        for (int m=NDIM;m--;)
     559          Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m]  = Force.Matrix[MatrixNumber][ k ][l+m];
     560        stored = tmp;
     561      }
     562    }
     563  }
    444564};
    445565
     
    450570void CreateSameForce(class MatrixContainer &Force, int MatrixNumber)
    451571{
    452         // does nothing
     572  // does nothing
    453573};
    454574
     
    460580void CreateVectorSumForce(class MatrixContainer &Force, int MatrixNumber)
    461581{
    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         }
     582  for (int l=Force.ColumnCounter[MatrixNumber];l--;)
     583    Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.;
     584  for (int l=0;l<Force.ColumnCounter[MatrixNumber];l++) {
     585    for (int k=Force.RowCounter[MatrixNumber];k--;)
     586      Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] += Force.Matrix[MatrixNumber][k][l];
     587  }
    468588};
    469589
     
    480600void 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)
    481601{
    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;
     602  //output << "#!/home/heber/build/pyxplot/pyxplot" << endl << endl;
     603  output << "reset" << endl;
     604  output << "set keycolumns "<< keycolumns << endl;
     605  output << "set key " << key << endl;
     606  output << "set mxtics "<< mxtics << endl;
     607  output << "set xtics "<< xtics << endl;
     608  if (logscale != NULL)
     609    output << "set logscale " << logscale << endl;
     610  if (extraline != NULL)
     611    output << extraline << endl;
     612  output << "set xlabel '" << xlabel << "'" << endl;
     613  output << "set ylabel '" << ylabel << "'" << endl;
     614  output << "set terminal eps color" << endl;
     615  output << "set output '"<< prefix << ".eps'" << endl;
    496616};
    497617
     
    517637bool 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 *))
    518638{
    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;
     639  stringstream filename;
     640  ofstream output;
     641
     642  filename << prefix << ".pyx";
     643  if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
     644  CreatePlotHeader(output, prefix, keycolumns, key, logscale, extraline, mxtics, xtics, xlabel, ylabel);
     645  output << "plot " << xrange << " " << yrange << " \\" << endl;
     646  CreatePlotLines(output, Matrix, prefix, xargument, uses);
     647  output.close();
     648  return true;
    529649};
    530650
     
    538658void AbsEnergyPlotLine(ofstream &output, class MatrixContainer &Energy, const char *prefix, const char *xargument, const char *uses)
    539659{
    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         }
     660  stringstream line(Energy.Header[ Energy.MatrixCounter ]);
     661  string token;
     662
     663  getline(line, token, '\t');
     664  for (int i=2; i<= Energy.ColumnCounter[Energy.MatrixCounter];i++) {
     665    getline(line, token, '\t');
     666    while (token[0] == ' ') // remove leading white spaces
     667      token.erase(0,1);
     668    output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(abs($" << i+2 << ")) " << uses;
     669    if (i != (Energy.ColumnCounter[Energy.MatrixCounter]))
     670      output << ", \\";
     671    output << endl;
     672  }
    553673};
    554674
     
    562682void EnergyPlotLine(ofstream &output, class MatrixContainer &Energy, const char *prefix, const char *xargument, const char *uses)
    563683{
    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         }
     684  stringstream line(Energy.Header[Energy.MatrixCounter]);
     685  string token;
     686
     687  getline(line, token, '\t');
     688  for (int i=1; i<= Energy.ColumnCounter[Energy.MatrixCounter];i++) {
     689    getline(line, token, '\t');
     690    while (token[0] == ' ') // remove leading white spaces
     691      token.erase(0,1);
     692    output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":" << i+2 << " " << uses;
     693    if (i != (Energy.ColumnCounter[Energy.MatrixCounter]))
     694      output << ", \\";
     695    output << endl;
     696  }
    577697};
    578698
     
    586706void ForceMagnitudePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses)
    587707{
    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         }
     708  stringstream line(Force.Header[Force.MatrixCounter]);
     709  string token;
     710
     711  getline(line, token, '\t');
     712  getline(line, token, '\t');
     713  getline(line, token, '\t');
     714  getline(line, token, '\t');
     715  getline(line, token, '\t');
     716  for (int i=7; i< Force.ColumnCounter[Force.MatrixCounter];i+=NDIM) {
     717    getline(line, token, '\t');
     718    while (token[0] == ' ') // remove leading white spaces
     719      token.erase(0,1);
     720    token.erase(token.length(), 1);  // kill residual index char (the '0')
     721    output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(sqrt($" << i+1 << "*$" << i+1 << "+$" << i+2 << "*$" << i+2 << "+$" << i+3 << "*$" << i+3 << ")) " << uses;
     722    if (i != (Force.ColumnCounter[Force.MatrixCounter]-1))
     723      output << ", \\";
     724    output << endl;
     725    getline(line, token, '\t');
     726    getline(line, token, '\t');
     727  }
    608728};
    609729
     
    617737void AbsFirstForceValuePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses)
    618738{
    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         }
     739  stringstream line(Force.Header[Force.MatrixCounter]);
     740  string token;
     741
     742  getline(line, token, '\t');
     743  getline(line, token, '\t');
     744  getline(line, token, '\t');
     745  getline(line, token, '\t');
     746  getline(line, token, '\t');
     747  for (int i=7; i< Force.ColumnCounter[Force.MatrixCounter];i+=NDIM) {
     748    getline(line, token, '\t');
     749    while (token[0] == ' ') // remove leading white spaces
     750      token.erase(0,1);
     751    token.erase(token.length(), 1);  // kill residual index char (the '0')
     752    output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(abs($" << i+1 << ")) " << uses;
     753    if (i != (Force.ColumnCounter[Force.MatrixCounter]-1))
     754      output << ", \\";
     755    output << endl;
     756    getline(line, token, '\t');
     757    getline(line, token, '\t');
     758  }
    639759};
    640760
     
    648768void BoxesForcePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses)
    649769{
    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         }
     770  stringstream line(Force.Header[Force.MatrixCounter]);
     771  char *fillcolor[5] = {"black", "red", "blue", "green", "cyan"};
     772  string token;
     773
     774  getline(line, token, '\t');
     775  getline(line, token, '\t');
     776  getline(line, token, '\t');
     777  getline(line, token, '\t');
     778  getline(line, token, '\t');
     779  for (int i=7; i< Force.ColumnCounter[Force.MatrixCounter];i+=NDIM) {
     780    getline(line, token, '\t');
     781    while (token[0] == ' ') // remove leading white spaces
     782      token.erase(0,1);
     783    token.erase(token.length(), 1);  // kill residual index char (the '0')
     784    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];
     785    if (i != (Force.ColumnCounter[Force.MatrixCounter]-1))
     786      output << ", \\";
     787    output << endl;
     788    getline(line, token, '\t');
     789    getline(line, token, '\t');
     790  }
    671791};
    672792
     
    680800void BoxesFirstForceValuePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses)
    681801{
    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 };
     802  stringstream line(Force.Header[Force.MatrixCounter]);
     803  char *fillcolor[5] = {"black", "red", "blue", "green", "cyan"};
     804  string token;
     805
     806  getline(line, token, '\t');
     807  getline(line, token, '\t');
     808  getline(line, token, '\t');
     809  getline(line, token, '\t');
     810  getline(line, token, '\t');
     811  for (int i=7; i< Force.ColumnCounter[Force.MatrixCounter];i+=NDIM) {
     812    getline(line, token, '\t');
     813    while (token[0] == ' ') // remove leading white spaces
     814      token.erase(0,1);
     815    token.erase(token.length(), 1);  // kill residual index char (the '0')
     816    output << "'" << prefix << ".dat' title '" << token << "' using ($" << xargument << "+" << fixed << setprecision(1) << (double)((i-7)/3)*0.2 << "):" << i+1 << " " << uses << " " << fillcolor[(i-7)/3];
     817    if (i != (Force.ColumnCounter[Force.MatrixCounter]-1))
     818      output << ", \\";
     819    output << endl;
     820    getline(line, token, '\t');
     821    getline(line, token, '\t');
     822  }
     823};
  • src/datacreator.hpp

    r375b458 r51c910  
    2525bool CreateDataForcesOrderPerAtom(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum);
    2626bool CreateDataDeltaForcesOrder(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateForce)(class MatrixContainer &, int));
    27 bool CreateDataDeltaForcesOrderPerAtom(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum);
     27bool CreateDataDeltaForcesOrderPerAtom(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum);
     28bool CreateDataHessianOrderPerAtom(class HessianMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum);
     29bool CreateDataDeltaHessianOrderPerAtom(class HessianMatrix &Hessian, class HessianMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum);
     30bool CreateDataDeltaFrobeniusOrderPerAtom(class HessianMatrix &Hessian, class HessianMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum);
    2831bool CreateDataFragment(class MatrixContainer &ForceFragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateForce)(class MatrixContainer &, int));
    2932bool CreateDataFragmentOrder(class MatrixContainer &Fragment, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateFragmentOrder)(class MatrixContainer &, class KeySetsContainer &, int));
  • src/defs.hpp

    r375b458 r51c910  
    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
     18#define KelvinToAtomicTemperature 3.1668152e-06    //!< conversion factor for Kelvin to atomic temperature (Hartree over k_B)
     19#define KelvinToeV 8.6173422e-05                   //!< conversion factor for Kelvin to Ht (k_B * T = energy), thus Boltzmann constant in eV/K
     20#define AtomicMassUnitsToeV 931494088.        //!< conversion factor for atomic weight in units to mass in eV
     21#define AtomicMassUnitsToHt 34480864.        //!< conversion factor for atomic weight in units to mass in Ht (protonmass/electronmass * electron_mass_in_Ht
     22#define ElectronMass_Ht 18778.865            //!< electron mass in Ht
     23#define ElectronMass_eV 510998.903           //!< electron mass in eV
     24#define Units2Electronmass (AtomicMassUnitsToeV/ElectronMass_eV) //!< atomic mass unit in eV/ electron mass in eV = 1 822.88863
     25#define Atomictime2Femtoseconds 0.024188843     //!< Atomictime in fs
     26
    1827#define VERSIONSTRING "v1.0"
    1928
     
    2433enum EdgeType { Undetermined, TreeEdge, BackEdge }; //!< edge type in a graph after Depth-First-Search analysis.
    2534
    26 enum Shading { white, lightgray, darkgray, black };     //!< color in Breadth-First-Search analysis
     35enum Shading { white, lightgray, darkgray, black };  //!< color in Breadth-First-Search analysis
    2736
    28 //enum CutCyclicBond { KeepBond,        SaturateBond }; //!< Saturation scheme either atom- or bondwise
     37//enum CutCyclicBond { KeepBond,  SaturateBond }; //!< Saturation scheme either atom- or bondwise
    2938
    3039// 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                                                         };
     40enum necessity { optional,    //!< parameter is optional, if not given sensible value is chosen
     41                 critical    //!< parameter must be given or programme won't initiate
     42              };
    3443
    3544// Specifying the status of the on command line given config file
     
    4352
    4453// 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
     54#define DEFAULTCONFIG "main_pcp_linux"    //!< default filename of config file
     55#define CONVEXENVELOPE "ConvexEnvelope.dat"    //!< default filename of convex envelope tecplot data file
     56#define KEYSETFILE "KeySets.dat"    //!< default filename of BOSSANOVA key sets file
     57#define ADJACENCYFILE "Adjacency.dat"    //!< default filename of BOSSANOVA adjacancy file
     58#define TEFACTORSFILE "TE-Factors.dat"    //!< default filename of BOSSANOVA total energy factors file
     59#define FORCESFILE "Forces-Factors.dat"    //!< default filename of BOSSANOVA force factors file
     60#define HCORRECTIONSUFFIX "Hcorrection.dat"    //!< default filename of BOSSANOVA H correction file (unwanted saturation interaction)
     61#define FITCONSTANTSUFFIX "FitConstant.dat"  //!< suffix of default filename of BOSSANOVA fit constants file (unwanted saturation interaction)
     62#define SHIELDINGSUFFIX "sigma_all.csv"                //!< default filename of BOSSANOVA shieldings file
     63#define SHIELDINGPASSUFFIX "sigma_all_PAS.csv"                //!< default filename of BOSSANOVA shieldings PAS file
     64#define ORDERATSITEFILE "OrderAtSite.dat"    //!< default filename of BOSSANOVA Bond Order at each atom file
     65#define ENERGYPERFRAGMENT "EnergyPerFragment"    //!< default filename of BOSSANOVA Energy contribution Per Fragment file
     66#define FRAGMENTPREFIX "BondFragment"    //!< default filename prefix of BOSSANOVA fragment config and directories
     67#define STANDARDCONFIG "unknown.conf"    //!< default filename of standard config file
     68#define STANDARDELEMENTSDB "elements.db"    //!< default filename of elements data base with masses, Z, VanDerWaals radii, ...
     69#define STANDARDVALENCEDB "valence.db"    //!< default filename of valence number per element database
     70#define STANDARDORBITALDB "orbitals.db"    //!< default filename of orbitals per element database
     71#define STANDARDHBONDDISTANCEDB "Hbonddistance.db"    //!< default filename of typial bond distance to hydrogen database
     72#define STANDARDHBONDANGLEDB "Hbondangle.db"    //!< default filename of typial bond angle to hydrogen database
    6473
    6574// some values
     
    6877
    6978
    70 #define UPDATECOUNT 10  //!< update ten sites per BOSSANOVA interval
     79#define UPDATECOUNT 10  //!< update ten sites per BOSSANOVA interval
    7180
    7281#endif /*DEFS_HPP_*/
  • src/ellipsoid.cpp

    r375b458 r51c910  
    217217        int PointsLeft = 0;
    218218        int PointsPicked = 0;
    219         double value, threshold;
    220219        int Nlower[NDIM], Nupper[NDIM];
    221220        set<int> PickedAtomNrs;  // ordered list of picked atoms
     
    274273                                PickedAtomNrs.insert(index);
    275274                        }
    276                 } while (PickedAtomNrs.size() < PointsToPick);
     275                } while (PickedAtomNrs.size() < (size_t) PointsToPick);
    277276
    278277                index = 0; // now go through all and pick those whose from PickedAtomsNr
  • src/graph.cpp

    r375b458 r51c910  
    77using namespace std;
    88
     9#include "graph.hpp"
    910
    10 #include <iostream>
    11 #include <list>
    12 #include <vector>
     11/***************************************** Implementations for graph classes ********************************/
    1312
    14 /***************************************** Functions for class graph ********************************/
     13/** Constructor of class Graph.
     14 */
     15Graph::Graph()
     16{
     17};
    1518
     19/** Destructor of class Graph.
     20 * Destructor does release memory for nodes and edges contained in its lists as well.
     21 */
     22Graph::~Graph()
     23{
     24};
    1625
     26/** Constructor of class SubGraph.
     27 */
     28SubGraph::SubGraph()
     29{
     30};
     31
     32/** Destructor of class SubGraph.
     33 * Note that destructor does not deallocate either nodes or edges! (this is done by its subgraph!)
     34 */
     35SubGraph::~SubGraph()
     36{
     37};
     38
     39/** Constructor of class Node.
     40 */
     41Node::Node()
     42{
     43};
     44
     45/** Destructor of class Node.
     46 */
     47Node::~Node()
     48{
     49};
     50
     51/** Constructor of class Edge.
     52 */
     53Edge::Edge()
     54{
     55};
     56
     57/** Destructor of class Edge.
     58 */
     59Edge::~Edge()
     60{
     61};
     62
  • src/helpers.cpp

    r375b458 r51c910  
    7171void * ReAlloc(void * OldPointer, size_t size, const char* output)
    7272{
    73         void *buffer = NULL;
    74         if (OldPointer == NULL)
    75                 //cout << Verbose(0) << "ReAlloc impossible - old is NULL: " << output << endl;
    76                 buffer = (void *)malloc(size); // malloc
    77         else
    78                 buffer = (void *)realloc(OldPointer, size); // realloc
    79         if (buffer == NULL)
    80                 cout << Verbose(0) << "ReAlloc failed - new is NULL: " << output << endl;
    81         return(buffer);
     73  void *buffer = NULL;
     74  if (OldPointer == NULL)
     75    //cout << Verbose(0) << "ReAlloc impossible - old is NULL: " << output << endl;
     76    buffer = (void *)malloc(size); // malloc
     77  else
     78    buffer = (void *)realloc(OldPointer, size); // realloc
     79  if (buffer == NULL)
     80    cout << Verbose(0) << "ReAlloc failed - new is NULL: " << output << endl;
     81  return(buffer);
    8282};
    8383
  • src/joiner.cpp

    r375b458 r51c910  
    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;
    34 
    35         cout << "Joiner" << endl;
    36         cout << "======" << endl;
    37 
    38         // Get the command line options
    39         if (argc < 3) {
    40                 cout << "Usage: " << argv[0] << " <inputdir> <prefix> [elementsdb]" << endl;
    41                 cout << "<inputdir>\ttherein the output of a molecuilder fragmentation is expected, each fragment with a subdir containing an energy.all and a forces.all file." << endl;
    42                 cout << "<prefix>\tprefix of energy and forces file." << endl;
    43                 cout << "[elementsdb]\tpath to elements database, needed for shieldings." << endl;
    44                 return 1;
    45         } else {
    46                 dir = (char *) Malloc(sizeof(char)*(strlen(argv[2])+2), "main: *dir");
    47                 strcpy(dir, "/");
    48                 strcat(dir, argv[2]);
    49         }
    50         if (argc > 3) {
    51                 periode = new periodentafel;
    52                 periode->LoadPeriodentafel(argv[3]);
    53         }
    54 
    55         // Test the given directory
    56         if (!TestParams(argc, argv))
    57                 return 1;
    58 
    59         // +++++++++++++++++ PARSING +++++++++++++++++++++++++++++++
    60 
    61         // ------------- Parse through all Fragment subdirs --------
    62         if (!Energy.ParseFragmentMatrix(argv[1], dir, EnergySuffix, 0,0)) return 1;
    63         Hcorrected = Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX, 0,0);
    64         if (!Force.ParseFragmentMatrix(argv[1], dir, ForcesSuffix, 0,0)) return 1;
    65         if (periode != NULL) { // also look for PAS values
    66                 if (!Shielding.ParseFragmentMatrix(argv[1], dir, ShieldingSuffix, 1, 0)) return 1;
    67                 if (!ShieldingPAS.ParseFragmentMatrix(argv[1], dir, ShieldingPASSuffix, 1, 0)) return 1;
    68         }
    69 
    70         // ---------- Parse the TE Factors into an array -----------------
    71         if (!Energy.ParseIndices()) return 1;
    72         if (Hcorrected) Hcorrection.ParseIndices();
    73 
    74         // ---------- Parse the Force indices into an array ---------------
    75         if (!Force.ParseIndices(argv[1])) return 1;
    76 
    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         }
    82 
    83         // ---------- Parse the KeySets into an array ---------------
    84         if (!KeySet.ParseKeySets(argv[1], Force.RowCounter, Force.MatrixCounter)) return 1;
    85 
    86         if (!KeySet.ParseManyBodyTerms()) return 1;
    87         if (!EnergyFragments.AllocateMatrix(Energy.Header, Energy.MatrixCounter, Energy.RowCounter, Energy.ColumnCounter)) return 1;
    88         if (Hcorrected) HcorrectionFragments.AllocateMatrix(Hcorrection.Header, Hcorrection.MatrixCounter, Hcorrection.RowCounter, Hcorrection.ColumnCounter);
    89         if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return 1;
    90         if (periode != NULL) { // also look for PAS values
    91                 if (!ShieldingFragments.AllocateMatrix(Shielding.Header, Shielding.MatrixCounter, Shielding.RowCounter, Shielding.ColumnCounter)) return 1;
    92                 if (!ShieldingPASFragments.AllocateMatrix(ShieldingPAS.Header, ShieldingPAS.MatrixCounter, ShieldingPAS.RowCounter, ShieldingPAS.ColumnCounter)) return 1;
    93         }
    94 
    95         // ----------- Resetting last matrices (where full QM values are stored right now)
    96         if(!Energy.SetLastMatrix(0., 0)) return 1;
    97         if(!Force.SetLastMatrix(0., 2)) return 1;
    98         if (periode != NULL) { // also look for PAS values
    99                 if(!Shielding.SetLastMatrix(0., 2)) return 1;
    100                 if(!ShieldingPAS.SetLastMatrix(0., 2)) return 1;
    101         }
    102 
    103         // +++++++++++++++++ SUMMING +++++++++++++++++++++++++++++++
    104 
    105         // --------- sum up and write for each order----------------
    106         for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
    107                 // --------- sum up energy --------------------
    108                 cout << "Summing energy of order " << BondOrder+1 << " ..." << endl;
    109                 if (!EnergyFragments.SumSubManyBodyTerms(Energy, KeySet, BondOrder)) return 1;
    110                 if (Hcorrected) {
    111                         HcorrectionFragments.SumSubManyBodyTerms(Hcorrection, KeySet, BondOrder);
    112                         if (!Energy.SumSubEnergy(EnergyFragments, &HcorrectionFragments, KeySet, BondOrder, 1.)) return 1;
    113                         if (Hcorrected) Hcorrection.SumSubEnergy(HcorrectionFragments, NULL, KeySet, BondOrder, 1.);
    114                 } else
    115                         if (!Energy.SumSubEnergy(EnergyFragments, NULL, KeySet, BondOrder, 1.)) return 1;
    116                 // --------- sum up Forces --------------------
    117                 cout << "Summing forces of order " << BondOrder+1 << " ..." << endl;
    118                 if (!ForceFragments.SumSubManyBodyTerms(Force, KeySet, BondOrder)) return 1;
    119                 if (!Force.SumSubForces(ForceFragments, KeySet, BondOrder, 1.)) return 1;
    120                 if (periode != NULL) { // also look for PAS values
    121                         cout << "Summing shieldings of order " << BondOrder+1 << " ..." << endl;
    122                         if (!ShieldingFragments.SumSubManyBodyTerms(Shielding, KeySet, BondOrder)) return 1;
    123                         if (!Shielding.SumSubForces(ShieldingFragments, KeySet, BondOrder, 1.)) return 1;
    124                         if (!ShieldingPASFragments.SumSubManyBodyTerms(ShieldingPAS, KeySet, BondOrder)) return 1;
    125                         if (!ShieldingPAS.SumSubForces(ShieldingPASFragments, KeySet, BondOrder, 1.)) return 1;
    126                 }
    127 
    128                 // --------- write the energy and forces file --------------------
    129                 prefix.str(" ");
    130                 prefix << dir << OrderSuffix << (BondOrder+1);
    131                 cout << "Writing files " << argv[1] << prefix.str() << ". ..." << endl;
    132                 // energy
    133                 if (!Energy.WriteLastMatrix(argv[1], (prefix.str()).c_str(), EnergySuffix)) return 1;
    134                 // forces
    135                 if (!Force.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ForcesSuffix)) return 1;
    136                 // shieldings
    137                 if (periode != NULL) { // also look for PAS values
    138                         if (!Shielding.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ShieldingSuffix)) return 1;
    139                         if (!ShieldingPAS.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ShieldingPASSuffix)) return 1;
    140                 }
    141         }
    142         // fragments
    143         prefix.str(" ");
    144         prefix << dir << EnergyFragmentSuffix;
    145         if (!EnergyFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
    146         if (Hcorrected) {
    147                 prefix.str(" ");
    148                 prefix << dir << HcorrectionFragmentSuffix;
    149                 if (!HcorrectionFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
    150         }
    151         prefix.str(" ");
    152         prefix << dir << ForceFragmentSuffix;
    153         if (!ForceFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
    154         if (!CreateDataFragment(EnergyFragments, KeySet, argv[1], FRAGMENTPREFIX ENERGYPERFRAGMENT, "fragment energy versus the Fragment No", "today", CreateEnergy)) return 1;
    155         if (periode != NULL) { // also look for PAS values
    156                 prefix.str(" ");
    157                 prefix << dir << ShieldingFragmentSuffix;
    158                 if (!ShieldingFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
    159                 prefix.str(" ");
    160                 prefix << dir << ShieldingPASFragmentSuffix;
    161                 if (!ShieldingPASFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
    162         }
    163 
    164         // write last matrices as fragments into central dir (not subdir as above), for analyzer to know index bounds
    165         if (!Energy.WriteLastMatrix(argv[1], dir, EnergyFragmentSuffix)) return 1;
    166         if (Hcorrected) Hcorrection.WriteLastMatrix(argv[1], dir, HcorrectionFragmentSuffix);
    167         if (!Force.WriteLastMatrix(argv[1], dir, ForceFragmentSuffix)) return 1;
    168         if (periode != NULL) { // also look for PAS values
    169                 if (!Shielding.WriteLastMatrix(argv[1], dir, ShieldingFragmentSuffix)) return 1;
    170                 if (!ShieldingPAS.WriteLastMatrix(argv[1], dir, ShieldingPASFragmentSuffix)) return 1;
    171         }
    172 
    173         // exit
    174         delete(periode);
    175         Free((void **)&dir, "main: *dir");
    176         cout << "done." << endl;
    177         return 0;
     19  periodentafel *periode = NULL; // and a period table of all elements
     20  EnergyMatrix Energy;
     21  EnergyMatrix EnergyFragments;
     22 
     23  EnergyMatrix Hcorrection;
     24  EnergyMatrix HcorrectionFragments;
     25 
     26  ForceMatrix Force;
     27  ForceMatrix ForceFragments;
     28
     29  HessianMatrix Hessian;
     30  HessianMatrix HessianFragments;
     31 
     32  ForceMatrix Shielding;
     33  ForceMatrix ShieldingPAS;
     34  ForceMatrix ShieldingFragments;
     35  ForceMatrix ShieldingPASFragments;
     36  ForceMatrix Chi;
     37  ForceMatrix ChiPAS;
     38  ForceMatrix ChiFragments;
     39  ForceMatrix ChiPASFragments;
     40  KeySetsContainer KeySet; 
     41  stringstream prefix;
     42  char *dir = NULL;
     43  bool NoHCorrection = false;
     44  bool NoHessian = false;
     45
     46  cout << "Joiner" << endl;
     47  cout << "======" << endl;
     48
     49  // Get the command line options
     50  if (argc < 3) {
     51    cout << "Usage: " << argv[0] << " <inputdir> <prefix> [elementsdb]" << endl;
     52    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;
     53    cout << "<prefix>\tprefix of energy and forces file." << endl;
     54    cout << "[elementsdb]\tpath to elements database, needed for shieldings." << endl;
     55    return 1;
     56  } else {
     57    dir = (char *) Malloc(sizeof(char)*(strlen(argv[2])+2), "main: *dir");
     58    strcpy(dir, "/");
     59    strcat(dir, argv[2]);
     60  }
     61  if (argc > 3) {
     62    periode = new periodentafel;
     63    periode->LoadPeriodentafel(argv[3]);
     64  }
     65
     66  // Test the given directory
     67  if (!TestParams(argc, argv))
     68    return 1;
     69
     70  // +++++++++++++++++ PARSING +++++++++++++++++++++++++++++++
     71
     72  // ------------- Parse through all Fragment subdirs --------
     73  if (!Energy.ParseFragmentMatrix(argv[1], dir, EnergySuffix, 0,0)) return 1;
     74  if (!Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX, 0,0)) {
     75    NoHCorrection = true;
     76    cout << "No HCorrection matrices found, skipping these." << endl;
     77  }
     78  if (!Force.ParseFragmentMatrix(argv[1], dir, ForcesSuffix, 0,0)) return 1;
     79  if (!Hessian.ParseFragmentMatrix(argv[1], dir, HessianSuffix, 0,0)) {
     80    NoHessian = true;
     81    cout << "No hessian matrices found, skipping these." << endl;
     82  }
     83  if (periode != NULL) { // also look for PAS values
     84    if (!Shielding.ParseFragmentMatrix(argv[1], dir, ShieldingSuffix, 1, 0)) return 1;
     85    if (!ShieldingPAS.ParseFragmentMatrix(argv[1], dir, ShieldingPASSuffix, 1, 0)) return 1;
     86    if (!Chi.ParseFragmentMatrix(argv[1], dir, ChiSuffix, 1, 0)) return 1;
     87    if (!ChiPAS.ParseFragmentMatrix(argv[1], dir, ChiPASSuffix, 1, 0)) return 1;
     88  }
     89
     90  // ---------- Parse the TE Factors into an array -----------------
     91  if (!Energy.InitialiseIndices()) return 1;
     92  if (!NoHCorrection)
     93    Hcorrection.InitialiseIndices();
     94 
     95  // ---------- Parse the Force indices into an array ---------------
     96  if (!Force.ParseIndices(argv[1])) return 1;
     97
     98  // ---------- Parse the Hessian (=force) indices into an array ---------------
     99  if (!NoHessian)
     100    if (!Hessian.InitialiseIndices((class MatrixContainer *)&Force)) 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(!Chi.ParseIndices(argv[1])) return 1;
     107    if(!ChiPAS.ParseIndices(argv[1])) return 1;
     108  }
     109
     110  // ---------- Parse the KeySets into an array ---------------
     111  if (!KeySet.ParseKeySets(argv[1], Force.RowCounter, Force.MatrixCounter)) return 1;
     112  if (!KeySet.ParseManyBodyTerms()) return 1;
     113
     114  if (!EnergyFragments.AllocateMatrix(Energy.Header, Energy.MatrixCounter, Energy.RowCounter, Energy.ColumnCounter)) return 1;
     115  if (!NoHCorrection) 
     116    HcorrectionFragments.AllocateMatrix(Hcorrection.Header, Hcorrection.MatrixCounter, Hcorrection.RowCounter, Hcorrection.ColumnCounter);
     117  if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return 1;
     118  if (!NoHessian)
     119    if (!HessianFragments.AllocateMatrix(Hessian.Header, Hessian.MatrixCounter, Hessian.RowCounter, Hessian.ColumnCounter)) return 1;
     120  if (periode != NULL) { // also look for PAS values
     121    if (!ShieldingFragments.AllocateMatrix(Shielding.Header, Shielding.MatrixCounter, Shielding.RowCounter, Shielding.ColumnCounter)) return 1;
     122    if (!ShieldingPASFragments.AllocateMatrix(ShieldingPAS.Header, ShieldingPAS.MatrixCounter, ShieldingPAS.RowCounter, ShieldingPAS.ColumnCounter)) return 1;
     123    if (!ChiFragments.AllocateMatrix(Chi.Header, Chi.MatrixCounter, Chi.RowCounter, Chi.ColumnCounter)) return 1;
     124    if (!ChiPASFragments.AllocateMatrix(ChiPAS.Header, ChiPAS.MatrixCounter, ChiPAS.RowCounter, ChiPAS.ColumnCounter)) return 1;
     125  }
     126
     127  // ----------- Resetting last matrices (where full QM values are stored right now)
     128  if(!Energy.SetLastMatrix(0., 0)) return 1;
     129  if(!Force.SetLastMatrix(0., 2)) return 1;
     130  if (!NoHessian)
     131    if (!Hessian.SetLastMatrix(0., 0)) return 1;
     132  if (periode != NULL) { // also look for PAS values
     133    if(!Shielding.SetLastMatrix(0., 2)) return 1;
     134    if(!ShieldingPAS.SetLastMatrix(0., 2)) return 1;
     135    if(!Chi.SetLastMatrix(0., 2)) return 1;
     136    if(!ChiPAS.SetLastMatrix(0., 2)) return 1;
     137  }
     138
     139  // +++++++++++++++++ SUMMING +++++++++++++++++++++++++++++++
     140
     141  // --------- sum up and write for each order----------------
     142  for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     143    // --------- sum up energy --------------------
     144    cout << "Summing energy of order " << BondOrder+1 << " ..." << endl;
     145    if (!EnergyFragments.SumSubManyBodyTerms(Energy, KeySet, BondOrder)) return 1;
     146    if (!NoHCorrection) {
     147      HcorrectionFragments.SumSubManyBodyTerms(Hcorrection, KeySet, BondOrder);
     148      if (!Energy.SumSubEnergy(EnergyFragments, &HcorrectionFragments, KeySet, BondOrder, 1.)) return 1;
     149      Hcorrection.SumSubEnergy(HcorrectionFragments, NULL, KeySet, BondOrder, 1.);
     150    } else
     151      if (!Energy.SumSubEnergy(EnergyFragments, NULL, KeySet, BondOrder, 1.)) return 1;
     152    // --------- sum up Forces --------------------
     153    cout << "Summing forces of order " << BondOrder+1 << " ..." << endl;
     154    if (!ForceFragments.SumSubManyBodyTerms(Force, KeySet, BondOrder)) return 1;
     155    if (!Force.SumSubForces(ForceFragments, KeySet, BondOrder, 1.)) return 1;
     156    // --------- sum up Hessian --------------------
     157    if (!NoHessian) {
     158      cout << "Summing Hessian of order " << BondOrder+1 << " ..." << endl;
     159      if (!HessianFragments.SumSubManyBodyTerms(Hessian, KeySet, BondOrder)) return 1;
     160      if (!Hessian.SumSubHessians(HessianFragments, KeySet, BondOrder, 1.)) return 1;
     161    }
     162    if (periode != NULL) { // also look for PAS values
     163      cout << "Summing shieldings and susceptibilities of order " << BondOrder+1 << " ..." << endl;
     164      if (!ShieldingFragments.SumSubManyBodyTerms(Shielding, KeySet, BondOrder)) return 1;
     165      if (!Shielding.SumSubForces(ShieldingFragments, KeySet, BondOrder, 1.)) return 1;
     166      if (!ShieldingPASFragments.SumSubManyBodyTerms(ShieldingPAS, KeySet, BondOrder)) return 1;
     167      if (!ShieldingPAS.SumSubForces(ShieldingPASFragments, KeySet, BondOrder, 1.)) return 1;
     168      if (!ChiFragments.SumSubManyBodyTerms(Chi, KeySet, BondOrder)) return 1;
     169      if (!Chi.SumSubForces(ChiFragments, KeySet, BondOrder, 1.)) return 1;
     170      if (!ChiPASFragments.SumSubManyBodyTerms(ChiPAS, KeySet, BondOrder)) return 1;
     171      if (!ChiPAS.SumSubForces(ChiPASFragments, KeySet, BondOrder, 1.)) return 1;
     172    }
     173
     174    // --------- write the energy and forces file --------------------
     175    prefix.str(" ");
     176    prefix << dir << OrderSuffix << (BondOrder+1);
     177    cout << "Writing files " << argv[1] << prefix.str() << ". ..." << endl;
     178    // energy
     179    if (!Energy.WriteLastMatrix(argv[1], (prefix.str()).c_str(), EnergySuffix)) return 1;
     180    // forces
     181    if (!Force.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ForcesSuffix)) return 1;
     182    // hessian
     183    if (!NoHessian)
     184      if (!Hessian.WriteLastMatrix(argv[1], (prefix.str()).c_str(), HessianSuffix)) return 1;
     185    // shieldings
     186    if (periode != NULL) { // also look for PAS values
     187      if (!Shielding.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ShieldingSuffix)) return 1;
     188      if (!ShieldingPAS.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ShieldingPASSuffix)) return 1;
     189      if (!Chi.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ChiSuffix)) return 1;
     190      if (!ChiPAS.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ChiPASSuffix)) return 1;
     191    }
     192  }
     193  // fragments
     194  prefix.str(" ");
     195  prefix << dir << EnergyFragmentSuffix;
     196  if (!EnergyFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
     197  if (!NoHCorrection) {
     198    prefix.str(" ");
     199    prefix << dir << HcorrectionFragmentSuffix;
     200    if (!HcorrectionFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
     201  }
     202  prefix.str(" ");
     203  prefix << dir << ForceFragmentSuffix;
     204  if (!ForceFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
     205  if (!CreateDataFragment(EnergyFragments, KeySet, argv[1], FRAGMENTPREFIX ENERGYPERFRAGMENT, "fragment energy versus the Fragment No", "today", CreateEnergy)) return 1;
     206  if (!NoHessian) {
     207    prefix.str(" ");
     208    prefix << dir << HessianFragmentSuffix;
     209    if (!HessianFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
     210  }
     211  if (periode != NULL) { // also look for PAS values
     212    prefix.str(" ");
     213    prefix << dir << ShieldingFragmentSuffix;
     214    if (!ShieldingFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
     215    prefix.str(" ");
     216    prefix << dir << ShieldingPASFragmentSuffix;
     217    if (!ShieldingPASFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
     218    prefix.str(" ");
     219    prefix << dir << ChiFragmentSuffix;
     220    if (!ChiFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
     221    prefix.str(" ");
     222    prefix << dir << ChiPASFragmentSuffix;
     223    if (!ChiPASFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;
     224  }
     225
     226  // write last matrices as fragments into central dir (not subdir as above), for analyzer to know index bounds
     227  if (!Energy.WriteLastMatrix(argv[1], dir, EnergyFragmentSuffix)) return 1;
     228  if (!NoHCorrection) Hcorrection.WriteLastMatrix(argv[1], dir, HcorrectionFragmentSuffix);
     229  if (!Force.WriteLastMatrix(argv[1], dir, ForceFragmentSuffix)) return 1;
     230  if (!NoHessian)
     231    if (!Hessian.WriteLastMatrix(argv[1], dir, HessianFragmentSuffix)) return 1;
     232  if (periode != NULL) { // also look for PAS values
     233    if (!Shielding.WriteLastMatrix(argv[1], dir, ShieldingFragmentSuffix)) return 1;
     234    if (!ShieldingPAS.WriteLastMatrix(argv[1], dir, ShieldingPASFragmentSuffix)) return 1;
     235    if (!Chi.WriteLastMatrix(argv[1], dir, ChiFragmentSuffix)) return 1;
     236    if (!ChiPAS.WriteLastMatrix(argv[1], dir, ChiPASFragmentSuffix)) return 1;
     237  }
     238
     239  // exit
     240  delete(periode);
     241  Free((void **)&dir, "main: *dir");
     242  cout << "done." << endl;
     243  return 0;
    178244};
    179245
  • src/moleculelist.cpp

    r375b458 r51c910  
    3535 * \return true - add successful
    3636 */
    37 bool MoleculeListClass::insert(molecule *mol)
     37void MoleculeListClass::insert(molecule *mol)
    3838{
    3939  mol->IndexNr = MaxIndex++;
     
    124124void MoleculeListClass::Enumerate(ofstream *out)
    125125{
    126   int i=1;
    127126  element* Elemental = NULL;
    128127  atom *Walker = NULL;
    129128  int Counts[MAX_ELEMENTS];
     129  double size=0;
     130  Vector Origin;
    130131
    131132  // header
    132   *out << "Index\tName\tNo.Atoms\tformula" << endl;
     133  *out << "Index\tName\t\tAtoms\tFormula\tCenter\tSize" << endl;
    133134  cout << Verbose(0) << "-----------------------------------------------" << endl;
    134135  if (ListOfMolecules.size() == 0)
    135136    *out << "\tNone" << endl;
    136137  else {
     138    Origin.Zero();
    137139    for (MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++) {
    138140      // reset element counts
    139141      for (int j = 0; j<MAX_ELEMENTS;j++)
    140142        Counts[j] = 0;
    141       // count atoms per element
     143      // count atoms per element and determine size of bounding sphere
     144      size=0.;
    142145      Walker = (*ListRunner)->start;
    143146      while (Walker->next != (*ListRunner)->end) {
    144147        Walker = Walker->next;
    145148        Counts[Walker->type->Z]++;
     149        if (Walker->x.DistanceSquared(&Origin) > size)
     150          size = Walker->x.DistanceSquared(&Origin);
    146151      }
    147152      // output Index, Name, number of atoms, chemical formula
    148153      *out << ((*ListRunner)->ActiveFlag ? "*" : " ") << (*ListRunner)->IndexNr << "\t" << (*ListRunner)->name << "\t\t" << (*ListRunner)->AtomCount << "\t";
    149154      Elemental = (*ListRunner)->elemente->end;
    150       while(Elemental != (*ListRunner)->elemente->start) {
     155      while(Elemental->previous != (*ListRunner)->elemente->start) {
    151156        Elemental = Elemental->previous;
    152157        if (Counts[Elemental->Z] != 0)
    153158          *out << Elemental->symbol << Counts[Elemental->Z];
    154159      }
    155       *out << endl;
     160      // Center and size
     161      *out << "\t" << (*ListRunner)->Center << "\t" << sqrt(size) << endl;
    156162    }
    157163  }
     
    164170molecule * MoleculeListClass::ReturnIndex(int index)
    165171{
    166   int count = 1;
    167   MoleculeList::iterator ListRunner = ListOfMolecules.begin();
    168   for(; ((ListRunner != ListOfMolecules.end()) && (count < index)); ListRunner++);
    169   if (count == index)
    170     return (*ListRunner);
    171   else
    172     return NULL;
     172  for(MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++)
     173    if ((*ListRunner)->IndexNr == index)
     174      return (*ListRunner);
     175  return NULL;
    173176};
    174177
     
    523526
    524527  // open file for the force factors
    525   *out << Verbose(1) << "Saving force factors ... ";
     528  *out << Verbose(1) << "Saving  force factors ... ";
    526529  line << path << "/" << FRAGMENTPREFIX << FORCESFILE;
    527530  ForcesFile.open(line.str().c_str(), ios::out);
     
    565568 * \param *configuration standard configuration to attach atoms in fragment molecule to.
    566569 * \param *SortIndex Index to map from the BFS labeling to the sequence how of Ion_Type in the config
     570 * \param DoPeriodic true - call ScanForPeriodicCorrection, false - don't
     571 * \param DoCentering true - call molecule::CenterEdge(), false - don't
    567572 * \return true - success (each file was written), false - something went wrong.
    568573 */
    569 bool MoleculeListClass::OutputConfigForListOfFragments(ofstream *out,
    570     config *configuration, int *SortIndex)
     574bool MoleculeListClass::OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex)
    571575{
    572576  ofstream outputFragment;
     
    691695MoleculeLeafClass::MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf = NULL)
    692696{
    693   //    if (Up != NULL)
    694   //            if (Up->DownLeaf == NULL) // are we the first down leaf for the upper leaf?
    695   //                    Up->DownLeaf = this;
    696   //    UpLeaf = Up;
    697   //    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;
    698702  Leaf = NULL;
    699703  previous = PreviousLeaf;
     
    711715MoleculeLeafClass::~MoleculeLeafClass()
    712716{
    713   //    if (DownLeaf != NULL) {// drop leaves further down
    714   //            MoleculeLeafClass *Walker = DownLeaf;
    715   //            MoleculeLeafClass *Next;
    716   //            do {
    717   //                    Next = Walker->NextLeaf;
    718   //                    delete(Walker);
    719   //                    Walker = Next;
    720   //            } while (Walker != NULL);
    721   //            // Last Walker sets DownLeaf automatically to NULL
    722   //    }
     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  //  }
    723727  // remove the leaf itself
    724728  if (Leaf != NULL) {
     
    729733  if (previous != NULL)
    730734    previous->next = next;
    731   //    } else { // we are first in list (connects to UpLeaf->DownLeaf)
    732   //            if ((NextLeaf != NULL) && (NextLeaf->UpLeaf == NULL))
    733   //                    NextLeaf->UpLeaf = UpLeaf;      // either null as we are top level or the upleaf of the first node
    734   //            if (UpLeaf != NULL)
    735   //                    UpLeaf->DownLeaf = NextLeaf;    // either null as we are only leaf or NextLeaf if we are just the first
    736   //    }
    737   //    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;
    738742  if (next != NULL) // are we last in list
    739743    next->previous = previous;
  • src/molecules.cpp

    r375b458 r51c910  
    6363  cell_size[1] = cell_size[3] = cell_size[4]= 0.;
    6464  strcpy(name,"none");
     65  IndexNr  = -1;
     66  ActiveFlag = false;
    6567};
    6668
     
    602604 * \param *filename filename
    603605 */
    604 void molecule::SetNameFromFilename(char *filename)
     606void molecule::SetNameFromFilename(const char *filename)
    605607{
    606608  int length = 0;
    607609  char *molname = strrchr(filename, '/')+sizeof(char);  // search for filename without dirs
    608   char *endname = strrchr(filename, '.');
     610  char *endname = strchr(molname, '.');
    609611  if ((endname == NULL) || (endname < molname))
    610612    length = strlen(molname);
     
    612614    length = strlen(molname) - strlen(endname);
    613615  strncpy(name, molname, length);
     616  name[length]='\0';
    614617};
    615618
     
    668671    max->Scale(0.5);
    669672    Translate(max);
     673    Center.Zero();
    670674  }
    671675
     
    707711    max->AddVector(min);
    708712    Translate(min);
     713    Center.Zero();
    709714  }
    710715  delete(min);
     
    716721 * \param *center return vector for translation vector
    717722 */
    718 void molecule::CenterOrigin(ofstream *out, Vector *center)
     723void molecule::CenterOrigin(ofstream *out)
    719724{
    720725  int Num = 0;
    721726  atom *ptr = start->next;  // start at first in list
    722727
    723   for(int i=NDIM;i--;) // zero center vector
    724     center->x[i] = 0.;
     728  Center.Zero();
    725729
    726730  if (ptr != end) {   //list not empty?
     
    728732      ptr = ptr->next;
    729733      Num++;
    730       center->AddVector(&ptr->x);
    731     }
    732     center->Scale(-1./Num); // divide through total number (and sign for direction)
    733     Translate(center);
     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();
    734739  }
    735740};
     
    796801 * \param *center return vector for translation vector
    797802 */
    798 void molecule::CenterGravity(ofstream *out, Vector *center)
    799 {
    800   if (center == NULL) {
    801     DetermineCenter(*center);
    802     Translate(center);
    803     delete(center);
    804   } else {
    805     Translate(center);
    806   }
     803void molecule::CenterPeriodic(ofstream *out)
     804{
     805  DeterminePeriodicCenter(Center);
     806};
     807
     808/** Centers the center of gravity of the atoms at (0,0,0).
     809 * \param *out output stream for debugging
     810 * \param *center return vector for translation vector
     811 */
     812void molecule::CenterAtVector(ofstream *out, Vector *newcenter)
     813{
     814  Center.CopyVector(newcenter);
    807815};
    808816
     
    853861
    854862/** Determines center of molecule (yet not considering atom masses).
    855  * \param Center reference to return vector
    856  */
    857 void molecule::DetermineCenter(Vector &Center)
     863 * \param center reference to return vector
     864 */
     865void molecule::DeterminePeriodicCenter(Vector &center)
    858866{
    859867  atom *Walker = start;
     
    865873
    866874  do {
    867     Center.Zero();
     875    center.Zero();
    868876    flag = true;
    869877    while (Walker->next != end) {
     
    892900        Testvector.AddVector(&Translationvector);
    893901        Testvector.MatrixMultiplication(matrix);
    894         Center.AddVector(&Testvector);
     902        center.AddVector(&Testvector);
    895903        cout << Verbose(1) << "vector is: ";
    896904        Testvector.Output((ofstream *)&cout);
     
    905913            Testvector.AddVector(&Translationvector);
    906914            Testvector.MatrixMultiplication(matrix);
    907             Center.AddVector(&Testvector);
     915            center.AddVector(&Testvector);
    908916            cout << Verbose(1) << "Hydrogen vector is: ";
    909917            Testvector.Output((ofstream *)&cout);
     
    916924  } while (!flag);
    917925  Free((void **)&matrix, "molecule::DetermineCenter: *matrix");
    918   Center.Scale(1./(double)AtomCount);
     926  center.Scale(1./(double)AtomCount);
    919927};
    920928
     
    929937  Vector *CenterOfGravity = DetermineCenterOfGravity(out);
    930938
    931   CenterGravity(out, CenterOfGravity);
     939  CenterAtVector(out, CenterOfGravity);
    932940
    933941  // reset inertia tensor
     
    10251033};
    10261034
     1035/** Evaluates the potential energy used for constrained molecular dynamics.
     1036 * \f$V_i^{con} = c^{bond} \cdot | r_{P(i)} - R_i | + sum_{i \neq j} C^{min} \cdot \frac{1}{C_{ij}} + C^{inj} \Bigl (1 - \theta \bigl (\prod_{i \neq j} (P(i) - P(j)) \bigr ) \Bigr )\f$
     1037 *     where the first term points to the target in minimum distance, the second is a penalty for trajectories lying too close to each other (\f$C_{ij}$ is minimum distance between
     1038 *     trajectories i and j) and the third term is a penalty for two atoms trying to each the same target point.
     1039 * Note that for the second term we have to solve the following linear system:
     1040 * \f$-c_1 \cdot n_1 + c_2 \cdot n_2 + C \cdot n_3 = - p_2 + p_1\f$, where \f$c_1\f$, \f$c_2\f$ and \f$C\f$ are constants,
     1041 * offset vector \f$p_1\f$ in direction \f$n_1\f$, offset vector \f$p_2\f$ in direction \f$n_2\f$,
     1042 * \f$n_3\f$ is the normal vector to both directions. \f$C\f$ would be the minimum distance between the two lines.
     1043 * \sa molecule::MinimiseConstrainedPotential(), molecule::VerletForceIntegration()
     1044 * \param *out output stream for debugging
     1045 * \param *PermutationMap gives target ptr for each atom, array of size molecule::AtomCount (this is "x" in \f$ V^{con}(x) \f$ )
     1046 * \param startstep start configuration (MDStep in molecule::trajectories)
     1047 * \param endstep end configuration (MDStep in molecule::trajectories)
     1048 * \param *constants constant in front of each term
     1049 * \param IsAngstroem whether coordinates are in angstroem (true) or bohrradius (false)
     1050 * \return potential energy
     1051 * \note This routine is scaling quadratically which is not optimal.
     1052 * \todo There's a bit double counting going on for the first time, bu nothing to worry really about.
     1053 */
     1054double molecule::ConstrainedPotential(ofstream *out, atom **PermutationMap, int startstep, int endstep, double *constants, bool IsAngstroem)
     1055{
     1056  double result = 0., tmp, Norm1, Norm2;
     1057  atom *Walker = NULL, *Runner = NULL, *Sprinter = NULL;
     1058  Vector trajectory1, trajectory2, normal, TestVector;
     1059  gsl_matrix *A = gsl_matrix_alloc(NDIM,NDIM);
     1060  gsl_vector *x = gsl_vector_alloc(NDIM);
     1061
     1062  // go through every atom
     1063  Walker = start;
     1064  while (Walker->next != end) {
     1065    Walker = Walker->next;
     1066    // first term: distance to target
     1067    Runner = PermutationMap[Walker->nr];   // find target point
     1068    tmp = (Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Runner].R.at(endstep)));
     1069    tmp *= IsAngstroem ? 1. : 1./AtomicLengthToAngstroem;
     1070    result += constants[0] * tmp;
     1071    //*out << Verbose(4) << "Adding " << tmp*constants[0] << "." << endl;
     1072   
     1073    // second term: sum of distances to other trajectories
     1074    Runner = start;
     1075    while (Runner->next != end) {
     1076      Runner = Runner->next;
     1077      if (Runner == Walker) // hence, we only go up to the Walker, not beyond (similar to i=0; i<j; i++)
     1078        break;
     1079      // determine normalized trajectories direction vector (n1, n2)
     1080      Sprinter = PermutationMap[Walker->nr];   // find first target point
     1081      trajectory1.CopyVector(&Trajectories[Sprinter].R.at(endstep));
     1082      trajectory1.SubtractVector(&Trajectories[Walker].R.at(startstep));
     1083      trajectory1.Normalize();
     1084      Norm1 = trajectory1.Norm();
     1085      Sprinter = PermutationMap[Runner->nr];   // find second target point
     1086      trajectory2.CopyVector(&Trajectories[Sprinter].R.at(endstep));
     1087      trajectory2.SubtractVector(&Trajectories[Runner].R.at(startstep));
     1088      trajectory2.Normalize();
     1089      Norm2 = trajectory1.Norm();
     1090      // check whether either is zero()
     1091      if ((Norm1 < MYEPSILON) && (Norm2 < MYEPSILON)) {
     1092        tmp = Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Runner].R.at(startstep));
     1093      } else if (Norm1 < MYEPSILON) {
     1094        Sprinter = PermutationMap[Walker->nr];   // find first target point
     1095        trajectory1.CopyVector(&Trajectories[Sprinter].R.at(endstep));  // copy first offset
     1096        trajectory1.SubtractVector(&Trajectories[Runner].R.at(startstep));  // subtract second offset
     1097        trajectory2.Scale( trajectory1.ScalarProduct(&trajectory2) ); // trajectory2 is scaled to unity, hence we don't need to divide by anything
     1098        trajectory1.SubtractVector(&trajectory2);   // project the part in norm direction away
     1099        tmp = trajectory1.Norm();  // remaining norm is distance
     1100      } else if (Norm2 < MYEPSILON) {
     1101        Sprinter = PermutationMap[Runner->nr];   // find second target point
     1102        trajectory2.CopyVector(&Trajectories[Sprinter].R.at(endstep));  // copy second offset
     1103        trajectory2.SubtractVector(&Trajectories[Walker].R.at(startstep));  // subtract first offset
     1104        trajectory1.Scale( trajectory2.ScalarProduct(&trajectory1) ); // trajectory1 is scaled to unity, hence we don't need to divide by anything
     1105        trajectory2.SubtractVector(&trajectory1);   // project the part in norm direction away
     1106        tmp = trajectory2.Norm();  // remaining norm is distance
     1107      } else if ((fabs(trajectory1.ScalarProduct(&trajectory2)/Norm1/Norm2) - 1.) < MYEPSILON) { // check whether they're linear dependent
     1108//        *out << Verbose(3) << "Both trajectories of " << *Walker << " and " << *Runner << " are linear dependent: ";
     1109//        *out << trajectory1;
     1110//        *out << " and ";
     1111//        *out << trajectory2;
     1112        tmp = Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Runner].R.at(startstep));
     1113//        *out << " with distance " << tmp << "." << endl;
     1114      } else { // determine distance by finding minimum distance
     1115//        *out << Verbose(3) << "Both trajectories of " << *Walker << " and " << *Runner << " are linear independent ";
     1116//        *out << endl;
     1117//        *out << "First Trajectory: ";
     1118//        *out << trajectory1 << endl;
     1119//        *out << "Second Trajectory: ";
     1120//        *out << trajectory2 << endl;
     1121        // determine normal vector for both
     1122        normal.MakeNormalVector(&trajectory1, &trajectory2);
     1123        // print all vectors for debugging
     1124//        *out << "Normal vector in between: ";
     1125//        *out << normal << endl;
     1126        // setup matrix
     1127        for (int i=NDIM;i--;) {
     1128          gsl_matrix_set(A, 0, i, trajectory1.x[i]);
     1129          gsl_matrix_set(A, 1, i, trajectory2.x[i]);
     1130          gsl_matrix_set(A, 2, i, normal.x[i]);
     1131          gsl_vector_set(x,i, (Trajectories[Walker].R.at(startstep).x[i] - Trajectories[Runner].R.at(startstep).x[i]));
     1132        }
     1133        // solve the linear system by Householder transformations
     1134        gsl_linalg_HH_svx(A, x);
     1135        // distance from last component
     1136        tmp = gsl_vector_get(x,2);
     1137//        *out << " with distance " << tmp << "." << endl;
     1138        // test whether we really have the intersection (by checking on c_1 and c_2)
     1139        TestVector.CopyVector(&Trajectories[Runner].R.at(startstep));
     1140        trajectory2.Scale(gsl_vector_get(x,1));
     1141        TestVector.AddVector(&trajectory2);
     1142        normal.Scale(gsl_vector_get(x,2));
     1143        TestVector.AddVector(&normal);
     1144        TestVector.SubtractVector(&Trajectories[Walker].R.at(startstep));
     1145        trajectory1.Scale(gsl_vector_get(x,0));
     1146        TestVector.SubtractVector(&trajectory1);
     1147        if (TestVector.Norm() < MYEPSILON) {
     1148//          *out << Verbose(2) << "Test: ok.\tDistance of " << tmp << " is correct." << endl; 
     1149        } else {
     1150//          *out << Verbose(2) << "Test: failed.\tIntersection is off by ";
     1151//          *out << TestVector;
     1152//          *out << "." << endl; 
     1153        }
     1154      }
     1155      // add up
     1156      tmp *= IsAngstroem ? 1. : 1./AtomicLengthToAngstroem;
     1157      if (fabs(tmp) > MYEPSILON) {
     1158        result += constants[1] * 1./tmp;
     1159        //*out << Verbose(4) << "Adding " << 1./tmp*constants[1] << "." << endl;
     1160      }
     1161    }
     1162     
     1163    // third term: penalty for equal targets
     1164    Runner = start;
     1165    while (Runner->next != end) {
     1166      Runner = Runner->next;
     1167      if ((PermutationMap[Walker->nr] == PermutationMap[Runner->nr]) && (Walker->nr < Runner->nr)) {
     1168        Sprinter = PermutationMap[Walker->nr];
     1169//        *out << *Walker << " and " << *Runner << " are heading to the same target at ";
     1170//        *out << Trajectories[Sprinter].R.at(endstep);
     1171//        *out << ", penalting." << endl;
     1172        result += constants[2];
     1173        //*out << Verbose(4) << "Adding " << constants[2] << "." << endl;
     1174      }
     1175    }
     1176  }
     1177 
     1178  return result;
     1179};
     1180
     1181void PrintPermutationMap(ofstream *out, atom **PermutationMap, int Nr)
     1182{
     1183  stringstream zeile1, zeile2;
     1184  int *DoubleList = (int *) Malloc(Nr*sizeof(int), "PrintPermutationMap: *DoubleList");
     1185  int doubles = 0;
     1186  for (int i=0;i<Nr;i++)
     1187    DoubleList[i] = 0;
     1188  zeile1 << "PermutationMap: ";
     1189  zeile2 << "                ";
     1190  for (int i=0;i<Nr;i++) {
     1191    DoubleList[PermutationMap[i]->nr]++;
     1192    zeile1 << i << " ";
     1193    zeile2 << PermutationMap[i]->nr << " ";
     1194  }
     1195  for (int i=0;i<Nr;i++)
     1196    if (DoubleList[i] > 1)
     1197    doubles++;
     1198 // *out << "Found " << doubles << " Doubles." << endl;
     1199  Free((void **)&DoubleList, "PrintPermutationMap: *DoubleList");
     1200//  *out << zeile1.str() << endl << zeile2.str() << endl;
     1201};
     1202
     1203/** Minimises the extra potential for constrained molecular dynamics and gives forces and the constrained potential energy.
     1204 * We do the following:
     1205 *  -# Generate a distance list from all source to all target points
     1206 *  -# Sort this per source point
     1207 *  -# Take for each source point the target point with minimum distance, use this as initial permutation
     1208 *  -# check whether molecule::ConstrainedPotential() is greater than injective penalty
     1209 *     -# If so, we go through each source point, stepping down in the sorted target point distance list and re-checking potential.
     1210 *  -# Next, we only apply transformations that keep the injectivity of the permutations list.
     1211 *  -# Hence, for one source point we step down the ladder and seek the corresponding owner of this new target
     1212 *     point and try to change it for one with lesser distance, or for the next one with greater distance, but only
     1213 *     if this decreases the conditional potential.
     1214 *  -# finished.
     1215 *  -# Then, we calculate the forces by taking the spatial derivative, where we scale the potential to such a degree,
     1216 *     that the total force is always pointing in direction of the constraint force (ensuring that we move in the
     1217 *     right direction).
     1218 *  -# Finally, we calculate the potential energy and return.
     1219 * \param *out output stream for debugging
     1220 * \param **PermutationMap on return: mapping between the atom label of the initial and the final configuration
     1221 * \param startstep current MD step giving initial position between which and \a endstep we perform the constrained MD (as further steps are always concatenated)
     1222 * \param endstep step giving final position in constrained MD
     1223 * \param IsAngstroem whether coordinates are in angstroem (true) or bohrradius (false)
     1224 * \sa molecule::VerletForceIntegration()
     1225 * \return potential energy (and allocated **PermutationMap (array of molecule::AtomCount ^2)
     1226 * \todo The constrained potential's constants are set to fixed values right now, but they should scale based on checks of the system in order
     1227 *       to ensure they're properties (e.g. constants[2] always greater than the energy of the system).
     1228 * \bug this all is not O(N log N) but O(N^2)
     1229 */
     1230double molecule::MinimiseConstrainedPotential(ofstream *out, atom **&PermutationMap, int startstep, int endstep, bool IsAngstroem)
     1231{
     1232  double Potential, OldPotential, OlderPotential;
     1233  PermutationMap = (atom **) Malloc(AtomCount*sizeof(atom *), "molecule::MinimiseConstrainedPotential: **PermutationMap");
     1234  DistanceMap **DistanceList = (DistanceMap **) Malloc(AtomCount*sizeof(DistanceMap *), "molecule::MinimiseConstrainedPotential: **DistanceList");
     1235  DistanceMap::iterator *DistanceIterators = (DistanceMap::iterator *) Malloc(AtomCount*sizeof(DistanceMap::iterator), "molecule::MinimiseConstrainedPotential: *DistanceIterators");
     1236  int *DoubleList = (int *) Malloc(AtomCount*sizeof(int), "molecule::MinimiseConstrainedPotential: *DoubleList");
     1237  DistanceMap::iterator *StepList = (DistanceMap::iterator *) Malloc(AtomCount*sizeof(DistanceMap::iterator), "molecule::MinimiseConstrainedPotential: *StepList");
     1238  double constants[3];
     1239  int round;
     1240  atom *Walker = NULL, *Runner = NULL, *Sprinter = NULL;
     1241  DistanceMap::iterator Rider, Strider;
     1242 
     1243  /// Minimise the potential
     1244  // set Lagrange multiplier constants
     1245  constants[0] = 10.;
     1246  constants[1] = 1.;
     1247  constants[2] = 1e+7;    // just a huge penalty
     1248  // generate the distance list
     1249  *out << Verbose(1) << "Creating the distance list ... " << endl;
     1250  for (int i=AtomCount; i--;) {
     1251    DoubleList[i] = 0;  // stores for how many atoms in startstep this atom is a target in endstep
     1252    DistanceList[i] = new DistanceMap;    // is the distance sorted target list per atom
     1253    DistanceList[i]->clear();
     1254  }
     1255  *out << Verbose(1) << "Filling the distance list ... " << endl;
     1256  Walker = start;
     1257  while (Walker->next != end) {
     1258    Walker = Walker->next;
     1259    Runner = start;
     1260    while(Runner->next != end) {
     1261      Runner = Runner->next;
     1262      DistanceList[Walker->nr]->insert( DistancePair(Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Runner].R.at(endstep)), Runner) );
     1263    }
     1264  }
     1265  // create the initial PermutationMap (source -> target)
     1266  Walker = start;
     1267  while (Walker->next != end) {
     1268    Walker = Walker->next;
     1269    StepList[Walker->nr] = DistanceList[Walker->nr]->begin();    // stores the step to the next iterator that could be a possible next target
     1270    PermutationMap[Walker->nr] = DistanceList[Walker->nr]->begin()->second;   // always pick target with the smallest distance
     1271    DoubleList[DistanceList[Walker->nr]->begin()->second->nr]++;            // increase this target's source count (>1? not injective)
     1272    DistanceIterators[Walker->nr] = DistanceList[Walker->nr]->begin();    // and remember which one we picked
     1273    *out << *Walker << " starts with distance " << DistanceList[Walker->nr]->begin()->first << "." << endl;
     1274  }
     1275  *out << Verbose(1) << "done." << endl;
     1276  // make the PermutationMap injective by checking whether we have a non-zero constants[2] term in it
     1277  *out << Verbose(1) << "Making the PermutationMap injective ... " << endl;
     1278  Walker = start;
     1279  DistanceMap::iterator NewBase;
     1280  OldPotential = fabs(ConstrainedPotential(out, PermutationMap, startstep, endstep, constants, IsAngstroem));
     1281  while ((OldPotential) > constants[2]) {
     1282    PrintPermutationMap(out, PermutationMap, AtomCount);
     1283    Walker = Walker->next;
     1284    if (Walker == end) // round-robin at the end
     1285      Walker = start->next;
     1286    if (DoubleList[DistanceIterators[Walker->nr]->second->nr] <= 1)  // no need to make those injective that aren't
     1287      continue;
     1288    // now, try finding a new one
     1289    NewBase = DistanceIterators[Walker->nr];  // store old base
     1290    do {
     1291      NewBase++;  // take next further distance in distance to targets list that's a target of no one
     1292    } while ((DoubleList[NewBase->second->nr] != 0) && (NewBase != DistanceList[Walker->nr]->end()));
     1293    if (NewBase != DistanceList[Walker->nr]->end()) {
     1294      PermutationMap[Walker->nr] = NewBase->second;
     1295      Potential = fabs(ConstrainedPotential(out, PermutationMap, startstep, endstep, constants, IsAngstroem));
     1296      if (Potential > OldPotential) { // undo
     1297        PermutationMap[Walker->nr] = DistanceIterators[Walker->nr]->second;
     1298      } else {  // do
     1299        DoubleList[DistanceIterators[Walker->nr]->second->nr]--;  // decrease the old entry in the doubles list
     1300        DoubleList[NewBase->second->nr]++;    // increase the old entry in the doubles list
     1301        DistanceIterators[Walker->nr] = NewBase;
     1302        OldPotential = Potential;
     1303        *out << Verbose(3) << "Found a new permutation, new potential is " << OldPotential << "." << endl;
     1304      }
     1305    }
     1306  }
     1307  for (int i=AtomCount; i--;) // now each single entry in the DoubleList should be <=1
     1308    if (DoubleList[i] > 1) {
     1309      cerr << "Failed to create an injective PermutationMap!" << endl;
     1310      exit(1);
     1311    }
     1312  *out << Verbose(1) << "done." << endl;
     1313  Free((void **)&DoubleList, "molecule::MinimiseConstrainedPotential: *DoubleList");
     1314  // argument minimise the constrained potential in this injective PermutationMap
     1315  *out << Verbose(1) << "Argument minimising the PermutationMap, at current potential " << OldPotential << " ... " << endl;
     1316  OldPotential = 1e+10;
     1317  round = 0;
     1318  do {
     1319    *out << "Starting round " << ++round << " ... " << endl;
     1320    OlderPotential = OldPotential;
     1321    do {
     1322      Walker = start;
     1323      while (Walker->next != end) { // pick one
     1324        Walker = Walker->next;
     1325        PrintPermutationMap(out, PermutationMap, AtomCount);
     1326        Sprinter = DistanceIterators[Walker->nr]->second;   // store initial partner
     1327        Strider = DistanceIterators[Walker->nr];  //remember old iterator
     1328        DistanceIterators[Walker->nr] = StepList[Walker->nr]; 
     1329        if (DistanceIterators[Walker->nr] == DistanceList[Walker->nr]->end()) {// stop, before we run through the list and still on
     1330          DistanceIterators[Walker->nr] == DistanceList[Walker->nr]->begin();
     1331          break;
     1332        }
     1333        //*out << Verbose(2) << "Current Walker: " << *Walker << " with old/next candidate " << *Sprinter << "/" << *DistanceIterators[Walker->nr]->second << "." << endl;
     1334        // find source of the new target
     1335        Runner = start->next;
     1336        while(Runner != end) { // find the source whose toes we might be stepping on (Walker's new target should be in use by another already)
     1337          if (PermutationMap[Runner->nr] == DistanceIterators[Walker->nr]->second) {
     1338            //*out << Verbose(2) << "Found the corresponding owner " << *Runner << " to " << *PermutationMap[Runner->nr] << "." << endl;
     1339            break;
     1340          }
     1341          Runner = Runner->next;
     1342        }
     1343        if (Runner != end) { // we found the other source
     1344          // then look in its distance list for Sprinter
     1345          Rider = DistanceList[Runner->nr]->begin();
     1346          for (; Rider != DistanceList[Runner->nr]->end(); Rider++)
     1347            if (Rider->second == Sprinter)
     1348              break;
     1349          if (Rider != DistanceList[Runner->nr]->end()) { // if we have found one
     1350            //*out << Verbose(2) << "Current Other: " << *Runner << " with old/next candidate " << *PermutationMap[Runner->nr] << "/" << *Rider->second << "." << endl;
     1351            // exchange both
     1352            PermutationMap[Walker->nr] = DistanceIterators[Walker->nr]->second; // put next farther distance into PermutationMap
     1353            PermutationMap[Runner->nr] = Sprinter;  // and hand the old target to its respective owner
     1354            PrintPermutationMap(out, PermutationMap, AtomCount);
     1355            // calculate the new potential
     1356            //*out << Verbose(2) << "Checking new potential ..." << endl;
     1357            Potential = ConstrainedPotential(out, PermutationMap, startstep, endstep, constants, IsAngstroem);
     1358            if (Potential > OldPotential) { // we made everything worse! Undo ...
     1359              //*out << Verbose(3) << "Nay, made the potential worse: " << Potential << " vs. " << OldPotential << "!" << endl;
     1360              //*out << Verbose(3) << "Setting " << *Runner << "'s source to " << *DistanceIterators[Runner->nr]->second << "." << endl;
     1361              // Undo for Runner (note, we haven't moved the iteration yet, we may use this)
     1362              PermutationMap[Runner->nr] = DistanceIterators[Runner->nr]->second;
     1363              // Undo for Walker
     1364              DistanceIterators[Walker->nr] = Strider;  // take next farther distance target
     1365              //*out << Verbose(3) << "Setting " << *Walker << "'s source to " << *DistanceIterators[Walker->nr]->second << "." << endl;
     1366              PermutationMap[Walker->nr] = DistanceIterators[Walker->nr]->second;
     1367            } else {
     1368              DistanceIterators[Runner->nr] = Rider;  // if successful also move the pointer in the iterator list
     1369              *out << Verbose(3) << "Found a better permutation, new potential is " << Potential << " vs." << OldPotential << "." << endl;
     1370              OldPotential = Potential;
     1371            }
     1372            if (Potential > constants[2]) {
     1373              cerr << "ERROR: The two-step permutation procedure did not maintain injectivity!" << endl;
     1374              exit(255);
     1375            }
     1376            //*out << endl;
     1377          } else {
     1378            cerr << "ERROR: " << *Runner << " was not the owner of " << *Sprinter << "!" << endl;
     1379            exit(255);
     1380          }
     1381        } else {
     1382          PermutationMap[Walker->nr] = DistanceIterators[Walker->nr]->second; // new target has no source!
     1383        }
     1384        StepList[Walker->nr]++; // take next farther distance target
     1385      }
     1386    } while (Walker->next != end);
     1387  } while ((OlderPotential - OldPotential) > 1e-3);
     1388  *out << Verbose(1) << "done." << endl;
     1389
     1390 
     1391  /// free memory and return with evaluated potential
     1392  for (int i=AtomCount; i--;)
     1393    DistanceList[i]->clear();
     1394  Free((void **)&DistanceList, "molecule::MinimiseConstrainedPotential: **DistanceList");
     1395  Free((void **)&DistanceIterators, "molecule::MinimiseConstrainedPotential: *DistanceIterators");
     1396  return ConstrainedPotential(out, PermutationMap, startstep, endstep, constants, IsAngstroem);
     1397};
     1398
     1399/** Evaluates the (distance-related part) of the constrained potential for the constrained forces.
     1400 * \param *out output stream for debugging
     1401 * \param startstep current MD step giving initial position between which and \a endstep we perform the constrained MD (as further steps are always concatenated)
     1402 * \param endstep step giving final position in constrained MD
     1403 * \param **PermutationMap mapping between the atom label of the initial and the final configuration
     1404 * \param *Force ForceMatrix containing force vectors from the external energy functional minimisation.
     1405 * \todo the constant for the constrained potential distance part is hard-coded independently of the hard-coded value in MinimiseConstrainedPotential()
     1406 */
     1407void molecule::EvaluateConstrainedForces(ofstream *out, int startstep, int endstep, atom **PermutationMap, ForceMatrix *Force)
     1408{
     1409  double constant = 10.;
     1410  atom *Walker = NULL, *Sprinter = NULL;
     1411 
     1412  /// evaluate forces (only the distance to target dependent part) with the final PermutationMap
     1413  *out << Verbose(1) << "Calculating forces and adding onto ForceMatrix ... " << endl;
     1414  Walker = start;
     1415  while (Walker->next != NULL) {
     1416    Walker = Walker->next;
     1417    Sprinter = PermutationMap[Walker->nr];
     1418    // set forces
     1419    for (int i=NDIM;i++;)
     1420      Force->Matrix[0][Walker->nr][5+i] += 2.*constant*sqrt(Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Sprinter].R.at(endstep)));
     1421  } 
     1422  *out << Verbose(1) << "done." << endl;
     1423};
     1424
     1425/** Performs a linear interpolation between two desired atomic configurations with a given number of steps.
     1426 * Note, step number is config::MaxOuterStep
     1427 * \param *out output stream for debugging
     1428 * \param startstep stating initial configuration in molecule::Trajectories
     1429 * \param endstep stating final configuration in molecule::Trajectories
     1430 * \param &config configuration structure
     1431 * \return true - success in writing step files, false - error writing files or only one step in molecule::Trajectories
     1432 */
     1433bool molecule::LinearInterpolationBetweenConfiguration(ofstream *out, int startstep, int endstep, const char *prefix, config &configuration)
     1434{
     1435  molecule *mol = NULL;
     1436  bool status = true;
     1437  int MaxSteps = configuration.MaxOuterStep;
     1438  MoleculeListClass *MoleculePerStep = new MoleculeListClass();
     1439  // Get the Permutation Map by MinimiseConstrainedPotential
     1440  atom **PermutationMap = NULL;
     1441  atom *Walker = NULL, *Sprinter = NULL;
     1442  MinimiseConstrainedPotential(out, PermutationMap, startstep, endstep, configuration.GetIsAngstroem());
     1443
     1444  // check whether we have sufficient space in Trajectories for each atom
     1445  Walker = start;
     1446  while (Walker->next != end) {
     1447    Walker = Walker->next;
     1448    if (Trajectories[Walker].R.size() <= (unsigned int)(MaxSteps)) {
     1449      //cout << "Increasing size for trajectory array of " << keyword << " to " << (MaxSteps+1) << "." << endl;
     1450      Trajectories[Walker].R.resize(MaxSteps+1);
     1451      Trajectories[Walker].U.resize(MaxSteps+1);
     1452      Trajectories[Walker].F.resize(MaxSteps+1);
     1453    }
     1454  }
     1455  // push endstep to last one
     1456  Walker = start;
     1457  while (Walker->next != end) { // remove the endstep (is now the very last one)
     1458    Walker = Walker->next;
     1459    for (int n=NDIM;n--;) {
     1460      Trajectories[Walker].R.at(MaxSteps).x[n] = Trajectories[Walker].R.at(endstep).x[n];
     1461      Trajectories[Walker].U.at(MaxSteps).x[n] = Trajectories[Walker].U.at(endstep).x[n];
     1462      Trajectories[Walker].F.at(MaxSteps).x[n] = Trajectories[Walker].F.at(endstep).x[n];
     1463    }
     1464  }
     1465  endstep = MaxSteps;
     1466 
     1467  // go through all steps and add the molecular configuration to the list and to the Trajectories of \a this molecule
     1468  *out << Verbose(1) << "Filling intermediate " << MaxSteps << " steps with MDSteps of " << MDSteps << "." << endl;
     1469  for (int step = 0; step <= MaxSteps; step++) {
     1470    mol = new molecule(elemente);
     1471    MoleculePerStep->insert(mol);
     1472    Walker = start;
     1473    while (Walker->next != end) {
     1474      Walker = Walker->next;
     1475      // add to molecule list
     1476      Sprinter = mol->AddCopyAtom(Walker);
     1477      for (int n=NDIM;n--;) {
     1478        Sprinter->x.x[n] = Trajectories[Walker].R.at(startstep).x[n] + (Trajectories[PermutationMap[Walker->nr]].R.at(endstep).x[n] - Trajectories[Walker].R.at(startstep).x[n])*((double)step/(double)MaxSteps);
     1479        // add to Trajectories
     1480        //*out << Verbose(3) << step << ">=" << MDSteps-1 << endl;
     1481        if (step < MaxSteps) {
     1482          Trajectories[Walker].R.at(step).x[n] = Trajectories[Walker].R.at(startstep).x[n] + (Trajectories[PermutationMap[Walker->nr]].R.at(endstep).x[n] - Trajectories[Walker].R.at(startstep).x[n])*((double)step/(double)MaxSteps);
     1483          Trajectories[Walker].U.at(step).x[n] = 0.;
     1484          Trajectories[Walker].F.at(step).x[n] = 0.;
     1485        }
     1486      }
     1487    }
     1488  }
     1489  MDSteps = MaxSteps+1;   // otherwise new Trajectories' points aren't stored on save&exit
     1490 
     1491  // store the list to single step files
     1492  int *SortIndex = (int *) Malloc(AtomCount*sizeof(int), "molecule::LinearInterpolationBetweenConfiguration: *SortIndex");
     1493  for (int i=AtomCount; i--; )
     1494    SortIndex[i] = i;
     1495  status = MoleculePerStep->OutputConfigForListOfFragments(out, &configuration, SortIndex);
     1496 
     1497  // free and return
     1498  Free((void **)&PermutationMap, "molecule::MinimiseConstrainedPotential: *PermutationMap");
     1499  delete(MoleculePerStep);
     1500  return status;
     1501};
     1502
    10271503/** Parses nuclear forces from file and performs Verlet integration.
    10281504 * Note that we assume the parsed forces to be in atomic units (hence, if coordinates are in angstroem, we
    10291505 * have to transform them).
    10301506 * This adds a new MD step to the config file.
     1507 * \param *out output stream for debugging
    10311508 * \param *file filename
     1509 * \param config structure with config::Deltat, config::IsAngstroem, config::DoConstrained
    10321510 * \param delta_t time step width in atomic units
    10331511 * \param IsAngstroem whether coordinates are in angstroem (true) or bohrradius (false)
     1512 * \param DoConstrained whether we perform a constrained (>0, target step in molecule::trajectories) or unconstrained (0) molecular dynamics, \sa molecule::MinimiseConstrainedPotential()
    10341513 * \return true - file found and parsed, false - file not found or imparsable
    1035  */
    1036 bool molecule::VerletForceIntegration(char *file, double delta_t, bool IsAngstroem)
    1037 {
    1038   element *runner = elemente->start;
     1514 * \todo This is not yet checked if it is correctly working with DoConstrained set to true.
     1515 */
     1516bool molecule::VerletForceIntegration(ofstream *out, char *file, config &configuration)
     1517{
    10391518  atom *walker = NULL;
    1040   int AtomNo;
    10411519  ifstream input(file);
    10421520  string token;
    10431521  stringstream item;
    1044   double a, IonMass;
     1522  double IonMass, Vector[NDIM], ConstrainedPotentialEnergy, ActualTemp;
    10451523  ForceMatrix Force;
    1046   Vector tmpvector;
    10471524
    10481525  CountElements();  // make sure ElementsInMolecule is up to date
     
    10621539    }
    10631540    // correct Forces
    1064 //    for(int d=0;d<NDIM;d++)
    1065 //      tmpvector.x[d] = 0.;
    1066 //    for(int i=0;i<AtomCount;i++)
    1067 //      for(int d=0;d<NDIM;d++) {
    1068 //        tmpvector.x[d] += Force.Matrix[0][i][d+5];
    1069 //      }
    1070 //    for(int i=0;i<AtomCount;i++)
    1071 //      for(int d=0;d<NDIM;d++) {
    1072 //        Force.Matrix[0][i][d+5] -= tmpvector.x[d]/(double)AtomCount;
    1073 //      }
     1541    for(int d=0;d<NDIM;d++)
     1542      Vector[d] = 0.;
     1543    for(int i=0;i<AtomCount;i++)
     1544      for(int d=0;d<NDIM;d++) {
     1545        Vector[d] += Force.Matrix[0][i][d+5];
     1546      }
     1547    for(int i=0;i<AtomCount;i++)
     1548      for(int d=0;d<NDIM;d++) {
     1549        Force.Matrix[0][i][d+5] -= Vector[d]/(double)AtomCount;
     1550      }
     1551    // solve a constrained potential if we are meant to
     1552    if (configuration.DoConstrainedMD) {
     1553      // calculate forces and potential
     1554      atom **PermutationMap = NULL;
     1555      ConstrainedPotentialEnergy = MinimiseConstrainedPotential(out, PermutationMap,configuration.DoConstrainedMD, 0, configuration.GetIsAngstroem());
     1556      EvaluateConstrainedForces(out, configuration.DoConstrainedMD, 0, PermutationMap, &Force);
     1557      Free((void **)&PermutationMap, "molecule::MinimiseConstrainedPotential: *PermutationMap");
     1558    }
     1559   
    10741560    // and perform Verlet integration for each atom with position, velocity and force vector
    1075     runner = elemente->start;
    1076     while (runner->next != elemente->end) { // go through every element
    1077       runner = runner->next;
    1078       IonMass = runner->mass;
    1079       a = delta_t*0.5/IonMass;        // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a
    1080       if (ElementsInMolecule[runner->Z]) { // if this element got atoms
    1081         AtomNo = 0;
     1561    walker = start;
     1562    while (walker->next != end) { // go through every atom of this element
     1563      walker = walker->next;
     1564      //a = configuration.Deltat*0.5/walker->type->mass;        // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a
     1565      // check size of vectors
     1566      if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) {
     1567        //out << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl;
     1568        Trajectories[walker].R.resize(MDSteps+10);
     1569        Trajectories[walker].U.resize(MDSteps+10);
     1570        Trajectories[walker].F.resize(MDSteps+10);
     1571      }
     1572     
     1573      // Update R (and F)
     1574      for (int d=0; d<NDIM; d++) {
     1575        Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][walker->nr][d+5]*(configuration.GetIsAngstroem() ? AtomicLengthToAngstroem : 1.);
     1576        Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d];
     1577        Trajectories[walker].R.at(MDSteps).x[d] += configuration.Deltat*(Trajectories[walker].U.at(MDSteps-1).x[d]);     // s(t) = s(0) + v * deltat + 1/2 a * deltat^2
     1578        Trajectories[walker].R.at(MDSteps).x[d] += 0.5*configuration.Deltat*configuration.Deltat*(Trajectories[walker].F.at(MDSteps).x[d]/walker->type->mass);     // F = m * a and s = 0.5 * F/m * t^2 = F * a * t
     1579      }
     1580      // Update U
     1581      for (int d=0; d<NDIM; d++) {
     1582        Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d];
     1583        Trajectories[walker].U.at(MDSteps).x[d] += configuration.Deltat * (Trajectories[walker].F.at(MDSteps).x[d]+Trajectories[walker].F.at(MDSteps-1).x[d]/walker->type->mass); // v = F/m * t
     1584      }
     1585//      out << "Integrated position&velocity of step " << (MDSteps) << ": (";
     1586//      for (int d=0;d<NDIM;d++)
     1587//        out << Trajectories[walker].R.at(MDSteps).x[d] << " ";          // next step
     1588//      out << ")\t(";
     1589//      for (int d=0;d<NDIM;d++)
     1590//        cout << Trajectories[walker].U.at(MDSteps).x[d] << " ";          // next step
     1591//      out << ")" << endl;
     1592            // next atom
     1593    }
     1594  }
     1595  // correct velocities (rather momenta) so that center of mass remains motionless
     1596  for(int d=0;d<NDIM;d++)
     1597    Vector[d] = 0.;
     1598  IonMass = 0.;
     1599  walker = start;
     1600  while (walker->next != end) { // go through every atom
     1601    walker = walker->next;
     1602    IonMass += walker->type->mass;  // sum up total mass
     1603    for(int d=0;d<NDIM;d++) {
     1604      Vector[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass;
     1605    }
     1606  }
     1607  // correct velocities (rather momenta) so that center of mass remains motionless
     1608  for(int d=0;d<NDIM;d++)
     1609    Vector[d] /= IonMass;
     1610  ActualTemp = 0.;
     1611  walker = start;
     1612  while (walker->next != end) { // go through every atom of this element
     1613    walker = walker->next;
     1614    for(int d=0;d<NDIM;d++) {
     1615      Trajectories[walker].U.at(MDSteps).x[d] -= Vector[d];
     1616      ActualTemp += 0.5 * walker->type->mass * Trajectories[walker].U.at(MDSteps).x[d] * Trajectories[walker].U.at(MDSteps).x[d];
     1617    }
     1618  }
     1619  Thermostats(configuration, ActualTemp, Berendsen);
     1620  MDSteps++;
     1621
     1622
     1623  // exit
     1624  return true;
     1625};
     1626
     1627/** Implementation of various thermostats.
     1628 * All these thermostats apply an additional force which has the following forms:
     1629 * -# Woodcock
     1630 *  \f$p_i \rightarrow \sqrt{\frac{T_0}{T}} \cdot p_i\f$
     1631 * -# Gaussian
     1632 *  \f$ \frac{ \sum_i \frac{p_i}{m_i} \frac{\partial V}{\partial q_i}} {\sum_i \frac{p^2_i}{m_i}} \cdot p_i\f$
     1633 * -# Langevin
     1634 *  \f$p_{i,n} \rightarrow \sqrt{1-\alpha^2} p_{i,0} + \alpha p_r\f$ 
     1635 * -# Berendsen
     1636 *  \f$p_i \rightarrow \left [ 1+ \frac{\delta t}{\tau_T} \left ( \frac{T_0}{T} \right ) \right ]^{\frac{1}{2}} \cdot p_i\f$
     1637 * -# Nose-Hoover
     1638 *  \f$\zeta p_i \f$ with \f$\frac{\partial \zeta}{\partial t} = \frac{1}{M_s} \left ( \sum^N_{i=1} \frac{p_i^2}{m_i} - g k_B T \right )\f$
     1639 * These Thermostats either simply rescale the velocities, thus this function should be called after ion velocities have been updated, and/or
     1640 * have a constraint force acting additionally on the ions. In the latter case, the ion speeds have to be modified
     1641 * belatedly and the constraint force set.
     1642 * \param *P Problem at hand
     1643 * \param i which of the thermostats to take: 0 - none, 1 - Woodcock, 2 - Gaussian, 3 - Langevin, 4 - Berendsen, 5 - Nose-Hoover
     1644 * \sa InitThermostat()
     1645 */
     1646void molecule::Thermostats(config &configuration, double ActualTemp, int Thermostat)
     1647{
     1648  double ekin = 0.;
     1649  double E = 0., G = 0.;
     1650  double delta_alpha = 0.;
     1651  double ScaleTempFactor;
     1652  double sigma;
     1653  double IonMass;
     1654  int d;
     1655  gsl_rng * r;
     1656  const gsl_rng_type * T;
     1657  double *U = NULL, *F = NULL, FConstraint[NDIM];
     1658  atom *walker = NULL;
     1659 
     1660  // calculate scale configuration
     1661  ScaleTempFactor = configuration.TargetTemp/ActualTemp;
     1662   
     1663  // differentating between the various thermostats
     1664  switch(Thermostat) {
     1665     case None:
     1666      cout << Verbose(2) <<  "Applying no thermostat..." << endl;
     1667      break;
     1668     case Woodcock:
     1669      if ((configuration.ScaleTempStep > 0) && ((MDSteps-1) % configuration.ScaleTempStep == 0)) {
     1670        cout << Verbose(2) <<  "Applying Woodcock thermostat..." << endl;
    10821671        walker = start;
    10831672        while (walker->next != end) { // go through every atom of this element
    10841673          walker = walker->next;
    1085           if (walker->type == runner) { // if this atom fits to element
    1086             // check size of vectors
    1087             if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) {
    1088               //cout << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl;
    1089               Trajectories[walker].R.resize(MDSteps+10);
    1090               Trajectories[walker].U.resize(MDSteps+10);
    1091               Trajectories[walker].F.resize(MDSteps+10);
     1674          IonMass = walker->type->mass;
     1675          U = Trajectories[walker].U.at(MDSteps).x;
     1676          if (walker->FixedIon == 0) // even FixedIon moves, only not by other's forces
     1677            for (d=0; d<NDIM; d++) {
     1678              U[d] *= sqrt(ScaleTempFactor);
     1679              ekin += 0.5*IonMass * U[d]*U[d];
    10921680            }
    1093             // 1. calculate x(t+\delta t)
    1094             for (int d=0; d<NDIM; d++) {
    1095               Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5];
    1096               Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d];
    1097               Trajectories[walker].R.at(MDSteps).x[d] += delta_t*(Trajectories[walker].U.at(MDSteps-1).x[d]);
    1098               Trajectories[walker].R.at(MDSteps).x[d] += 0.5*delta_t*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d])/IonMass;    // F = m * a and s = 0.5 * F/m * t^2 = F * a * t
     1681        }
     1682      }
     1683      break;
     1684     case Gaussian:
     1685      cout << Verbose(2) <<  "Applying Gaussian thermostat..." << endl;
     1686      walker = start;
     1687      while (walker->next != end) { // go through every atom of this element
     1688        walker = walker->next;
     1689        IonMass = walker->type->mass;
     1690        U = Trajectories[walker].U.at(MDSteps).x;
     1691        F = Trajectories[walker].F.at(MDSteps).x;
     1692        if (walker->FixedIon == 0) // even FixedIon moves, only not by other's forces
     1693          for (d=0; d<NDIM; d++) {
     1694            G += U[d] * F[d];
     1695            E += U[d]*U[d]*IonMass;
     1696          }
     1697      }
     1698      cout << Verbose(1) << "Gaussian Least Constraint constant is " << G/E << "." << endl;
     1699      walker = start;
     1700      while (walker->next != end) { // go through every atom of this element
     1701        walker = walker->next;
     1702        IonMass = walker->type->mass;
     1703        U = Trajectories[walker].U.at(MDSteps).x;
     1704        F = Trajectories[walker].F.at(MDSteps).x;
     1705        if (walker->FixedIon == 0) // even FixedIon moves, only not by other's forces
     1706          for (d=0; d<NDIM; d++) {
     1707            FConstraint[d] = (G/E) * (U[d]*IonMass);
     1708            U[d] += configuration.Deltat/IonMass * (FConstraint[d]);
     1709            ekin += IonMass * U[d]*U[d];
     1710          }
     1711      }
     1712      break;
     1713     case Langevin:
     1714      cout << Verbose(2) <<  "Applying Langevin thermostat..." << endl;
     1715      // init random number generator
     1716      gsl_rng_env_setup();
     1717      T = gsl_rng_default;
     1718      r = gsl_rng_alloc (T);
     1719      // Go through each ion
     1720      walker = start;
     1721      while (walker->next != end) { // go through every atom of this element
     1722        walker = walker->next;
     1723        IonMass = walker->type->mass;
     1724        sigma  = sqrt(configuration.TargetTemp/IonMass); // sigma = (k_b T)/m (Hartree/atomicmass = atomiclength/atomictime)
     1725        U = Trajectories[walker].U.at(MDSteps).x;
     1726        F = Trajectories[walker].F.at(MDSteps).x;
     1727        if (walker->FixedIon == 0) { // even FixedIon moves, only not by other's forces
     1728          // throw a dice to determine whether it gets hit by a heat bath particle
     1729          if (((((rand()/(double)RAND_MAX))*configuration.TempFrequency) < 1.)) { 
     1730            cout << Verbose(3) << "Particle " << *walker << " was hit (sigma " << sigma << "): " << sqrt(U[0]*U[0]+U[1]*U[1]+U[2]*U[2]) << " -> ";
     1731            // pick three random numbers from a Boltzmann distribution around the desired temperature T for each momenta axis
     1732            for (d=0; d<NDIM; d++) {
     1733              U[d] = gsl_ran_gaussian (r, sigma);
    10991734            }
    1100             // 2. Calculate v(t+\delta t)
    1101             for (int d=0; d<NDIM; d++) {
    1102               Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d];
    1103               Trajectories[walker].U.at(MDSteps).x[d] += 0.5*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d]+Trajectories[walker].F.at(MDSteps).x[d])/IonMass;
    1104             }
    1105 //            cout << "Integrated position&velocity of step " << (MDSteps) << ": (";
    1106 //            for (int d=0;d<NDIM;d++)
    1107 //              cout << Trajectories[walker].R.at(MDSteps).x[d] << " ";          // next step
    1108 //            cout << ")\t(";
    1109 //            for (int d=0;d<NDIM;d++)
    1110 //              cout << Trajectories[walker].U.at(MDSteps).x[d] << " ";          // next step
    1111 //            cout << ")" << endl;
    1112             // next atom
    1113             AtomNo++;
     1735            cout << sqrt(U[0]*U[0]+U[1]*U[1]+U[2]*U[2]) << endl;
     1736          }
     1737          for (d=0; d<NDIM; d++)
     1738            ekin += 0.5*IonMass * U[d]*U[d];
     1739        }
     1740      }
     1741      break;
     1742     case Berendsen:
     1743      cout << Verbose(2) <<  "Applying Berendsen-VanGunsteren thermostat..." << endl;
     1744      walker = start;
     1745      while (walker->next != end) { // go through every atom of this element
     1746        walker = walker->next;
     1747        IonMass = walker->type->mass;
     1748        U = Trajectories[walker].U.at(MDSteps).x;
     1749        F = Trajectories[walker].F.at(MDSteps).x;
     1750        if (walker->FixedIon == 0) { // even FixedIon moves, only not by other's forces
     1751          for (d=0; d<NDIM; d++) {
     1752            U[d] *= sqrt(1+(configuration.Deltat/configuration.TempFrequency)*(ScaleTempFactor-1));
     1753            ekin += 0.5*IonMass * U[d]*U[d];
    11141754          }
    11151755        }
    11161756      }
    1117     }
    1118   }
    1119 //  // correct velocities (rather momenta) so that center of mass remains motionless
    1120 //  tmpvector.zero()
    1121 //  IonMass = 0.;
    1122 //  walker = start;
    1123 //  while (walker->next != end) { // go through every atom
    1124 //    walker = walker->next;
    1125 //    IonMass += walker->type->mass;  // sum up total mass
    1126 //    for(int d=0;d<NDIM;d++) {
    1127 //      tmpvector.x[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass;
    1128 //    }
    1129 //  }
    1130 //  walker = start;
    1131 //  while (walker->next != end) { // go through every atom of this element
    1132 //    walker = walker->next;
    1133 //    for(int d=0;d<NDIM;d++) {
    1134 //      Trajectories[walker].U.at(MDSteps).x[d] -= tmpvector.x[d]*walker->type->mass/IonMass;
    1135 //    }
    1136 //  }
    1137   MDSteps++;
    1138 
    1139 
    1140   // exit
    1141   return true;
    1142 };
    1143 
    1144 /** Align all atoms in such a manner that given vector \a *n is along z axis.
     1757      break;
     1758     case NoseHoover:
     1759      cout << Verbose(2) <<  "Applying Nose-Hoover thermostat..." << endl;
     1760      // dynamically evolve alpha (the additional degree of freedom)
     1761      delta_alpha = 0.;
     1762      walker = start;
     1763      while (walker->next != end) { // go through every atom of this element
     1764        walker = walker->next;
     1765        IonMass = walker->type->mass;
     1766        U = Trajectories[walker].U.at(MDSteps).x;
     1767        if (walker->FixedIon == 0) { // even FixedIon moves, only not by other's forces
     1768          for (d=0; d<NDIM; d++) {
     1769            delta_alpha += U[d]*U[d]*IonMass;
     1770          }
     1771        }
     1772      }
     1773      delta_alpha = (delta_alpha - (3.*AtomCount+1.) * configuration.TargetTemp)/(configuration.HooverMass*Units2Electronmass);
     1774      configuration.alpha += delta_alpha*configuration.Deltat;
     1775      cout << Verbose(3) << "alpha = " << delta_alpha << " * " << configuration.Deltat << " = " << configuration.alpha << "." << endl;
     1776      // apply updated alpha as additional force
     1777      walker = start;
     1778      while (walker->next != end) { // go through every atom of this element
     1779        walker = walker->next;
     1780        IonMass = walker->type->mass;
     1781        U = Trajectories[walker].U.at(MDSteps).x;
     1782        if (walker->FixedIon == 0) { // even FixedIon moves, only not by other's forces
     1783          for (d=0; d<NDIM; d++) {
     1784              FConstraint[d] = - configuration.alpha * (U[d] * IonMass);
     1785              U[d] += configuration.Deltat/IonMass * (FConstraint[d]);
     1786              ekin += (0.5*IonMass) * U[d]*U[d];
     1787            }
     1788        }
     1789      }
     1790      break;
     1791  }   
     1792  cout << Verbose(1) << "Kinetic energy is " << ekin << "." << endl;
     1793};
     1794
     1795/** Align all atoms in such a manner that given vector \a *n is along z axis.
    11451796 * \param n[] alignment vector.
    11461797 */
     
    18002451  Vector x;
    18012452  int FalseBondDegree = 0;
    1802 
     2453 
    18032454  BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem);
    18042455  *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl;
     
    30433694  while (MolecularWalker->next != NULL) {
    30443695    MolecularWalker = MolecularWalker->next;
     3696    *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;
    30453697    LocalBackEdgeStack = new StackClass<bond *> (MolecularWalker->Leaf->BondCount);
    30463698//    // check the list of local atoms for debugging
     
    30583710    delete(LocalBackEdgeStack);
    30593711  }
    3060 
     3712 
    30613713  // ===== 3. if structure still valid, parse key set file and others =====
    30623714  FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList);
     
    30643716  // ===== 4. check globally whether there's something to do actually (first adaptivity check)
    30653717  FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath);
    3066 
    3067   // =================================== Begin of FRAGMENTATION ===============================
    3068   // ===== 6a. assign each keyset to its respective subgraph =====
     3718 
     3719  // =================================== Begin of FRAGMENTATION =============================== 
     3720  // ===== 6a. assign each keyset to its respective subgraph ===== 
    30693721  Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true);
    30703722
     
    31013753  delete(ParsedFragmentList);
    31023754  delete[](MinimumRingSize);
    3103 
     3755 
    31043756
    31053757  // ==================================== End of FRAGMENTATION ============================================
     
    31943846  atom *Walker = NULL, *OtherAtom = NULL;
    31953847  ReferenceStack->Push(Binder);
    3196 
     3848 
    31973849  do {  // go through all bonds and push local ones
    31983850    Walker = ListOfLocalAtoms[Binder->leftatom->nr];  // get one atom in the reference molecule
     
    36644316};
    36654317
     4318/** Creates \a MoleculeListClass of all unique fragments of the \a molecule containing \a Order atoms or vertices.
     4319 * The picture to have in mind is that of a DFS "snake" of a certain length \a Order, i.e. as in the infamous
     4320 * computer game, that winds through the connected graph representing the molecule. Color (white,
     4321 * lightgray, darkgray, black) indicates whether a vertex has been discovered so far or not. Labels will help in
     4322 * creating only unique fragments and not additional ones with vertices simply in different sequence.
     4323 * The Predecessor is always the one that came before in discovering, needed on backstepping. And
     4324 * finally, the ShortestPath is needed for removing vertices from the snake stack during the back-
     4325 * stepping.
     4326 * \param *out output stream for debugging
     4327 * \param Order number of atoms in each fragment
     4328 * \param *configuration configuration for writing config files for each fragment
     4329 * \return List of all unique fragments with \a Order atoms
     4330 */
     4331/*
     4332MoleculeListClass * molecule::CreateListOfUniqueFragmentsOfOrder(ofstream *out, int Order, config *configuration)
     4333{
     4334  atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: **PredecessorList");
     4335  int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *ShortestPathList");
     4336  int *Labels = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *Labels");
     4337  enum Shading *ColorVertexList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *ColorList");
     4338  enum Shading *ColorEdgeList = (enum Shading *) Malloc(sizeof(enum Shading)*BondCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *ColorBondList");
     4339  StackClass<atom *> *RootStack = new StackClass<atom *>(AtomCount);
     4340  StackClass<atom *> *TouchedStack = new StackClass<atom *>((int)pow(4,Order)+2); // number of atoms reached from one with maximal 4 bonds plus Root itself
     4341  StackClass<atom *> *SnakeStack = new StackClass<atom *>(Order+1); // equal to Order is not possible, as then the StackClass<atom *> cannot discern between full and empty stack!
     4342  MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL;
     4343  MoleculeListClass *FragmentList = NULL;
     4344  atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL, *Removal = NULL;
     4345  bond *Binder = NULL;
     4346  int RunningIndex = 0, FragmentCounter = 0;
     4347
     4348  *out << Verbose(1) << "Begin of CreateListOfUniqueFragmentsOfOrder." << endl;
     4349
     4350  // reset parent list
     4351  *out << Verbose(3) << "Resetting labels, parent, predecessor, color and shortest path lists." << endl;
     4352  for (int i=0;i<AtomCount;i++) { // reset all atom labels
     4353    // initialise each vertex as white with no predecessor, empty queue, color lightgray, not labelled, no sons
     4354    Labels[i] = -1;
     4355    SonList[i] = NULL;
     4356    PredecessorList[i] = NULL;
     4357    ColorVertexList[i] = white;
     4358    ShortestPathList[i] = -1;
     4359  }
     4360  for (int i=0;i<BondCount;i++)
     4361    ColorEdgeList[i] = white;
     4362  RootStack->ClearStack();  // clearstack and push first atom if exists
     4363  TouchedStack->ClearStack();
     4364  Walker = start->next;
     4365  while ((Walker != end)
     4366#ifdef ADDHYDROGEN
     4367   && (Walker->type->Z == 1)
     4368        }
     4369      }
     4370      *out << ", SP of " << ShortestPathList[Walker->nr]  << " and its color is " << GetColor(ColorVertexList[Walker->nr]) << "." << endl;
     4371
     4372      // then check the stack for a newly stumbled upon fragment
     4373      if (SnakeStack->ItemCount() == Order) { // is stack full?
     4374        // store the fragment if it is one and get a removal candidate
     4375        Removal = StoreFragmentFromStack(out, Root, Walker, Leaflet, SnakeStack, ShortestPathList, SonList, Labels, &FragmentCounter, configuration);
     4376        // remove the candidate if one was found
     4377        if (Removal != NULL) {
     4378          *out << Verbose(2) << "Removing item " << Removal->Name << " with SP of " << ShortestPathList[Removal->nr] << " from snake stack." << endl;
     4379          SnakeStack->RemoveItem(Removal);
     4380          ColorVertexList[Removal->nr] = lightgray; // return back to not on snake stack but explored marking
     4381          if (Walker == Removal) { // if the current atom is to be removed, we also have to take a step back
     4382            Walker = PredecessorList[Removal->nr];
     4383            *out << Verbose(2) << "Stepping back to " << Walker->Name << "." << endl;
     4384          }
     4385        }
     4386      } else
     4387        Removal = NULL;
     4388
     4389      // finally, look for a white neighbour as the next Walker
     4390      Binder = NULL;
     4391      if ((Removal == NULL) || (Walker != PredecessorList[Removal->nr])) {  // don't look, if a new walker has been set above
     4392        *out << Verbose(2) << "Snake has currently " << SnakeStack->ItemCount() << " item(s)." << endl;
     4393        OtherAtom = NULL; // this is actually not needed, every atom has at least one neighbour
     4394        if (ShortestPathList[Walker->nr] < Order) {
     4395          for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
     4396            Binder = ListOfBondsPerAtom[Walker->nr][i];
     4397            *out << Verbose(2) << "Current bond is " << *Binder << ": ";
     4398            OtherAtom = Binder->GetOtherAtom(Walker);
     4399            if ((Labels[OtherAtom->nr] != -1) && (Labels[OtherAtom->nr] < Labels[Root->nr])) { // we don't step up to labels bigger than us
     4400              *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl;
     4401              //ColorVertexList[OtherAtom->nr] = lightgray;    // mark as explored
     4402            } else { // otherwise check its colour and element
     4403              if (
     4404              (OtherAtom->type->Z != 1) &&
     4405#endif
     4406                    (ColorEdgeList[Binder->nr] == white)) {  // skip hydrogen, look for unexplored vertices
     4407                *out << "Moving along " << GetColor(ColorEdgeList[Binder->nr]) << " bond " << Binder << " to " << ((ColorVertexList[OtherAtom->nr] == white) ? "unexplored" : "explored") << " item: " << OtherAtom->Name << "." << endl;
     4408                // i find it currently rather sensible to always set the predecessor in order to find one's way back
     4409                //if (PredecessorList[OtherAtom->nr] == NULL) {
     4410                PredecessorList[OtherAtom->nr] = Walker;
     4411                *out << Verbose(3) << "Setting Predecessor of " << OtherAtom->Name << " to " << PredecessorList[OtherAtom->nr]->Name << "." << endl;
     4412                //} else {
     4413                //  *out << Verbose(3) << "Predecessor of " << OtherAtom->Name << " is " << PredecessorList[OtherAtom->nr]->Name << "." << endl;
     4414                //}
     4415                Walker = OtherAtom;
     4416                break;
     4417              } else {
     4418                if (OtherAtom->type->Z == 1)
     4419                  *out << "Links to a hydrogen atom." << endl;
     4420                else
     4421                  *out << "Bond has not white but " << GetColor(ColorEdgeList[Binder->nr]) << " color." << endl;
     4422              }
     4423            }
     4424          }
     4425        } else {  // means we have stepped beyond the horizon: Return!
     4426          Walker = PredecessorList[Walker->nr];
     4427          OtherAtom = Walker;
     4428          *out << Verbose(3) << "We have gone too far, stepping back to " << Walker->Name << "." << endl;
     4429        }
     4430        if (Walker != OtherAtom) {  // if no white neighbours anymore, color it black
     4431          *out << Verbose(2) << "Coloring " << Walker->Name << " black." << endl;
     4432          ColorVertexList[Walker->nr] = black;
     4433          Walker = PredecessorList[Walker->nr];
     4434        }
     4435      }
     4436    } while ((Walker != Root) || (ColorVertexList[Root->nr] != black));
     4437    *out << Verbose(2) << "Inner Looping is finished." << endl;
     4438
     4439    // if we reset all AtomCount atoms, we have again technically O(N^2) ...
     4440    *out << Verbose(2) << "Resetting lists." << endl;
     4441    Walker = NULL;
     4442    Binder = NULL;
     4443    while (!TouchedStack->IsEmpty()) {
     4444      Walker = TouchedStack->PopLast();
     4445      *out << Verbose(3) << "Re-initialising entries of " << *Walker << "." << endl;
     4446      for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++)
     4447        ColorEdgeList[ListOfBondsPerAtom[Walker->nr][i]->nr] = white;
     4448      PredecessorList[Walker->nr] = NULL;
     4449      ColorVertexList[Walker->nr] = white;
     4450      ShortestPathList[Walker->nr] = -1;
     4451    }
     4452  }
     4453  *out << Verbose(1) << "Outer Looping over all vertices is done." << endl;
     4454
     4455  // copy together
     4456  *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl;
     4457  FragmentList = new MoleculeListClass(FragmentCounter, AtomCount);
     4458  RunningIndex = 0;
     4459  while ((Leaflet != NULL) && (RunningIndex < FragmentCounter))  {
     4460    FragmentList->ListOfMolecules[RunningIndex++] = Leaflet->Leaf;
     4461    Leaflet->Leaf = NULL; // prevent molecule from being removed
     4462    TempLeaf = Leaflet;
     4463    Leaflet = Leaflet->previous;
     4464    delete(TempLeaf);
     4465  };
     4466
     4467  // free memory and exit
     4468  Free((void **)&PredecessorList, "molecule::CreateListOfUniqueFragmentsOfOrder: **PredecessorList");
     4469  Free((void **)&ShortestPathList, "molecule::CreateListOfUniqueFragmentsOfOrder: *ShortestPathList");
     4470  Free((void **)&Labels, "molecule::CreateListOfUniqueFragmentsOfOrder: *Labels");
     4471  Free((void **)&ColorVertexList, "molecule::CreateListOfUniqueFragmentsOfOrder: *ColorList");
     4472  delete(RootStack);
     4473  delete(TouchedStack);
     4474  delete(SnakeStack);
     4475
     4476  *out << Verbose(1) << "End of CreateListOfUniqueFragmentsOfOrder." << endl;
     4477  return FragmentList;
     4478};
     4479*/
     4480
    36664481/** Structure containing all values in power set combination generation.
    36674482 */
     
    44955310  if (result) {
    44965311    *out << Verbose(5) << "Calculating Centers of Gravity" << endl;
    4497     DetermineCenter(CenterOfGravity);
    4498     OtherMolecule->DetermineCenter(OtherCenterOfGravity);
     5312    DeterminePeriodicCenter(CenterOfGravity);
     5313    OtherMolecule->DeterminePeriodicCenter(OtherCenterOfGravity);
    44995314    *out << Verbose(5) << "Center of Gravity: ";
    45005315    CenterOfGravity.Output(out);
  • src/molecules.hpp

    r375b458 r51c910  
    1010
    1111// GSL headers
     12#include <gsl/gsl_eigen.h>
     13#include <gsl/gsl_heapsort.h>
     14#include <gsl/gsl_linalg.h>
     15#include <gsl/gsl_matrix.h>
    1216#include <gsl/gsl_multimin.h>
    1317#include <gsl/gsl_vector.h>
    14 #include <gsl/gsl_matrix.h>
    15 #include <gsl/gsl_eigen.h>
    16 #include <gsl/gsl_heapsort.h>
     18#include <gsl/gsl_randist.h>
    1719
    1820// STL headers
     
    7678struct KeyCompare
    7779{
    78         bool operator() (const KeySet SubgraphA, const KeySet SubgraphB) const;
     80  bool operator() (const KeySet SubgraphA, const KeySet SubgraphB) const;
    7981};
    8082
    8183struct Trajectory
    8284{
    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)
     85  vector<Vector> R;  //!< position vector
     86  vector<Vector> U;  //!< velocity vector
     87  vector<Vector> F;  //!< last force vector
     88  atom *ptr;        //!< pointer to atom whose trajectory we contain
     89};
     90
     91//bool operator < (KeySet SubgraphA, KeySet SubgraphB);  //note: this declaration is important, otherwise normal < is used (producing wrong order)
    9092inline 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
     93inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter);  // Insert all KeySet's in a Graph into another Graph
    9294int CompareDoubles (const void * a, const void * b);
    9395
     
    9799
    98100// 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
     101#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
     102#define RDET2(a0,a1,a2,a3) ((a0)*(a3)-(a1)*(a2))                      //!< hard-coded determinant of a 2x2 matrix
    101103
    102104
     
    104106 */
    105107struct LSQ_params {
    106         Vector **vectors;
    107         int num;
     108  Vector **vectors;
     109  int num;
    108110};
    109111
     
    113115 */
    114116struct lsq_params {
    115         gsl_vector *x;
    116         const molecule *mol;
    117         element *type;
     117  gsl_vector *x;
     118  const molecule *mol;
     119  element *type;
    118120};
    119121
     
    122124 */
    123125class 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:
    153 };
    154 
    155 ostream & operator << (ostream &ost, atom &a);
     126  public:
     127    Vector x;      //!< coordinate array of atom, giving position within cell
     128    Vector v;      //!< velocity array of atom
     129    element *type;  //!< pointing to element
     130    atom *previous; //!< previous atom in molecule list
     131    atom *next;    //!< next atom in molecule list
     132    atom *father;  //!< In many-body bond order fragmentations points to originating atom
     133    atom *Ancestor; //!< "Father" in Depth-First-Search
     134    char *Name;      //!< unique name used during many-body bond-order fragmentation
     135    int FixedIon;  //!< config variable that states whether forces act on the ion or not
     136    int *sort;      //!< sort criteria
     137    int nr;        //!< continuous, unique number
     138    int GraphNr;      //!< unique number, given in DepthFirstSearchAnalysis()
     139    int *ComponentNr;//!< belongs to this nonseparable components, given in DepthFirstSearchAnalysis() (if more than one, then is SeparationVertex)
     140    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.
     141    bool SeparationVertex; //!< whether this atom separates off subsets of atoms or not, determined in DepthFirstSearchAnalysis()
     142    bool IsCyclic;        //!< whether atom belong to as cycle or not, determined in DepthFirstSearchAnalysis()
     143    unsigned char AdaptiveOrder;  //!< current present bond order at site (0 means "not set")
     144    bool MaxOrder;  //!< whether this atom as a root in fragmentation still creates more fragments on higher orders or not
     145
     146  atom();
     147  ~atom();
     148
     149  bool Output(int ElementNo, int AtomNo, ofstream *out, const char *comment = NULL) const;
     150  bool OutputXYZLine(ofstream *out) const;
     151  atom *GetTrueFather();
     152  bool Compare(atom &ptr);
     153
     154  private:
     155};
     156
     157ostream & operator << (ostream &ost, const atom &a);
    156158
    157159/** Bonds between atoms.
     
    161163 */
    162164class 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()
    192 };
    193 
    194 ostream & operator << (ostream &ost, bond &b);
     165  public:
     166    atom *leftatom;    //!< first bond partner
     167    atom *rightatom;  //!< second bond partner
     168    bond *previous; //!< previous atom in molecule list
     169    bond *next;     //!< next atom in molecule list
     170    int HydrogenBond;  //!< Number of hydrogen atoms in the bond
     171    int BondDegree;    //!< single, double, triple, ... bond
     172    int nr;           //!< unique number in a molecule, updated by molecule::CreateAdjacencyList()
     173    bool Cyclic;      //!< flag whether bond is part of a cycle or not, given in DepthFirstSearchAnalysis()
     174    enum EdgeType Type;//!< whether this is a tree or back edge
     175
     176  atom * GetOtherAtom(atom *Atom) const;
     177  bond * GetFirstBond();
     178  bond * GetLastBond();
     179
     180  bool MarkUsed(enum Shading color);
     181  enum Shading IsUsed();
     182  void ResetUsed();
     183  bool Contains(const atom *ptr);
     184  bool Contains(const int nr);
     185
     186  bond();
     187  bond(atom *left, atom *right);
     188  bond(atom *left, atom *right, int degree);
     189  bond(atom *left, atom *right, int degree, int number);
     190  ~bond();
     191
     192  private:
     193    enum Shading Used;        //!< marker in depth-first search, DepthFirstSearchAnalysis()
     194};
     195
     196
     197ostream & operator << (ostream &ost, const bond &b);
    195198
    196199class MoleculeLeafClass;
     200
     201
     202#define MaxThermostats 6      //!< maximum number of thermostat entries in Ions#ThermostatNames and Ions#ThermostatImplemented
     203enum thermostats { None, Woodcock, Gaussian, Langevin, Berendsen, NoseHoover };   //!< Thermostat names for output
     204
    197205
    198206/** The complete molecule.
     
    200208 */
    201209class 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, Vector *max);
    254         void CenterGravity(ofstream *out, Vector *max);
    255         void Translate(const Vector *x);
    256         void Mirror(const Vector *x);
    257         void Align(Vector *n);
    258         void Scale(double **factor);
    259         void DetermineCenter(Vector &center);
    260         Vector * DetermineCenterOfGravity(ofstream *out);
    261         Vector * DetermineCenterOfAll(ofstream *out);
    262         void SetNameFromFilename(char *filename);
    263         void SetBoxDimension(Vector *dim);
    264         double * ReturnFullMatrixforSymmetric(double *cell_size);
    265         void ScanForPeriodicCorrection(ofstream *out);
    266         void PrincipalAxisSystem(ofstream *out, bool DoRotate);
    267         double VolumeOfConvexEnvelope(ofstream *out, bool IsAngstroem);
    268         Vector* FindEmbeddingHole(ofstream *out, molecule *srcmol);
    269 
    270         bool VerletForceIntegration(char *file, double delta_t, bool IsAngstroem);
    271 
    272         bool CheckBounds(const Vector *x) const;
    273         void GetAlignvector(struct lsq_params * par) const;
    274 
    275         /// Initialising routines in fragmentation
    276         void CreateAdjacencyList2(ofstream *out, ifstream *output);
    277         void CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem);
    278         void CreateListOfBondsPerAtom(ofstream *out);
    279 
    280         // Graph analysis
    281         MoleculeLeafClass * DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack);
    282         void CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> *BackEdgeStack, int *&MinimumRingSize);
    283         bool PickLocalBackEdges(ofstream *out, atom **ListOfLocalAtoms, class StackClass<bond *> *&ReferenceStack, class StackClass<bond *> *&LocalStack);
    284         bond * FindNextUnused(atom *vertex);
    285         void SetNextComponentNumber(atom *vertex, int nr);
    286         void InitComponentNumbers();
    287         void OutputComponentNumber(ofstream *out, atom *vertex);
    288         void ResetAllBondsToUnused();
    289         void ResetAllAtomNumbers();
    290         int CountCyclicBonds(ofstream *out);
    291         bool CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment);
    292         string GetColor(enum Shading color);
    293 
    294         molecule *CopyMolecule();
    295 
    296         /// Fragment molecule by two different approaches:
    297         int FragmentMolecule(ofstream *out, int Order, config *configuration);
    298         bool CheckOrderAtSite(ofstream *out, bool *AtomMask, Graph *GlobalKeySetList, int Order, int *MinimumRingSize, char *path = NULL);
    299         bool StoreAdjacencyToFile(ofstream *out, char *path);
    300         bool CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms);
    301         bool ParseOrderAtSiteFromFile(ofstream *out, char *path);
    302         bool StoreOrderAtSiteFile(ofstream *out, char *path);
    303         bool ParseKeySetFile(ofstream *out, char *filename, Graph *&FragmentList);
    304         bool StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path);
    305         bool StoreForcesFile(ofstream *out, MoleculeListClass *BondFragments, char *path, int *SortIndex);
    306         bool CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex);
    307         bool ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet);
    308         void BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem);
    309         /// -# BOSSANOVA
    310         void FragmentBOSSANOVA(ofstream *out, Graph *&FragmentList, KeyStack &RootStack, int *MinimumRingSize);
    311         int PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet);
    312         bool BuildInducedSubgraph(ofstream *out, const molecule *Father);
    313         molecule * StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem);
    314         void SPFragmentGenerator(ofstream *out, struct UniqueFragments *FragmentSearch, int RootDistance, bond **BondsSet, int SetDimension, int SubOrder);
    315         int LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList);
    316         int GuesstimateFragmentCount(ofstream *out, int order);
    317 
    318         // Recognize doubly appearing molecules in a list of them
    319         int * IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold);
    320         int * GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule);
    321 
    322         // Output routines.
    323         bool Output(ofstream *out);
    324         bool OutputTrajectories(ofstream *out);
    325         void OutputListOfBonds(ofstream *out) const;
    326         bool OutputXYZ(ofstream *out) const;
    327         bool OutputTrajectoriesXYZ(ofstream *out);
    328         bool Checkout(ofstream *out) const;
    329         bool OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output);
    330 
    331         private:
    332         int last_atom;                  //!< number given to last atom
     210  public:
     211    double cell_size[6];//!< cell size
     212    periodentafel *elemente; //!< periodic table with each element
     213    atom *start;        //!< start of atom list
     214    atom *end;          //!< end of atom list
     215    bond *first;        //!< start of bond list
     216    bond *last;         //!< end of bond list
     217    bond ***ListOfBondsPerAtom; //!< pointer list for each atom and each bond it has
     218    map<atom *, struct Trajectory> Trajectories; //!< contains old trajectory points
     219    int MDSteps;        //!< The number of MD steps in Trajectories
     220    int *NumberOfBondsPerAtom;  //!< Number of Bonds each atom has
     221    int AtomCount;          //!< number of atoms, brought up-to-date by CountAtoms()
     222    int BondCount;          //!< number of atoms, brought up-to-date by CountBonds()
     223    int ElementCount;       //!< how many unique elements are therein
     224    int ElementsInMolecule[MAX_ELEMENTS]; //!< list whether element (sorted by atomic number) is alread present or not
     225    int NoNonHydrogen;  //!< number of non-hydrogen atoms in molecule
     226    int NoNonBonds;     //!< number of non-hydrogen bonds in molecule
     227    int NoCyclicBonds;  //!< number of cyclic bonds in molecule, by DepthFirstSearchAnalysis()
     228    double BondDistance;  //!< typical bond distance used in CreateAdjacencyList() and furtheron
     229    bool ActiveFlag;    //!< in a MoleculeListClass used to discern active from inactive molecules
     230    Vector Center;      //!< Center of molecule in a global box
     231    char name[MAXSTRINGSIZE];         //!< arbitrary name
     232    int IndexNr;        //!< index of molecule in a MoleculeListClass
     233
     234  molecule(periodentafel *teil);
     235  ~molecule();
     236
     237  /// remove atoms from molecule.
     238  bool AddAtom(atom *pointer);
     239  bool RemoveAtom(atom *pointer);
     240  bool UnlinkAtom(atom *pointer);
     241  bool CleanupMolecule();
     242
     243  /// Add/remove atoms to/from molecule.
     244  atom * AddCopyAtom(atom *pointer);
     245  bool AddXYZFile(string filename);
     246  bool AddHydrogenReplacementAtom(ofstream *out, bond *Bond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem);
     247  bond * AddBond(atom *first, atom *second, int degree);
     248  bool RemoveBond(bond *pointer);
     249  bool RemoveBonds(atom *BondPartner);
     250
     251  /// Find atoms.
     252  atom * FindAtom(int Nr) const;
     253  atom * AskAtom(string text);
     254
     255  /// Count and change present atoms' coordination.
     256  void CountAtoms(ofstream *out);
     257  void CountElements();
     258  void CalculateOrbitals(class config &configuration);
     259  bool CenterInBox(ofstream *out, Vector *BoxLengths);
     260  void CenterEdge(ofstream *out, Vector *max);
     261  void CenterOrigin(ofstream *out);
     262  void CenterPeriodic(ofstream *out);
     263  void CenterAtVector(ofstream *out, Vector *newcenter);
     264  void Translate(const Vector *x);
     265  void Mirror(const Vector *x);
     266  void Align(Vector *n);
     267  void Scale(double **factor);
     268  void DeterminePeriodicCenter(Vector &center);
     269  Vector * DetermineCenterOfGravity(ofstream *out);
     270  Vector * DetermineCenterOfAll(ofstream *out);
     271  void SetNameFromFilename(const char *filename);
     272  void SetBoxDimension(Vector *dim);
     273  double * ReturnFullMatrixforSymmetric(double *cell_size);
     274  void ScanForPeriodicCorrection(ofstream *out);
     275  bool VerletForceIntegration(ofstream *out, char *file, config &configuration);
     276  void Thermostats(config &configuration, double ActualTemp, int Thermostat);
     277  void PrincipalAxisSystem(ofstream *out, bool DoRotate);
     278  double VolumeOfConvexEnvelope(ofstream *out, bool IsAngstroem);
     279  Vector* FindEmbeddingHole(ofstream *out, molecule *srcmol);
     280
     281
     282  double ConstrainedPotential(ofstream *out, atom **permutation, int start, int end, double *constants, bool IsAngstroem);
     283  double MinimiseConstrainedPotential(ofstream *out, atom **&permutation, int startstep, int endstep, bool IsAngstroem);
     284  void EvaluateConstrainedForces(ofstream *out, int startstep, int endstep, atom **PermutationMap, ForceMatrix *Force);
     285  bool LinearInterpolationBetweenConfiguration(ofstream *out, int startstep, int endstep, const char *prefix, config &configuration);
     286       
     287  bool CheckBounds(const Vector *x) const;
     288  void GetAlignvector(struct lsq_params * par) const;
     289
     290  /// Initialising routines in fragmentation
     291  void CreateAdjacencyList2(ofstream *out, ifstream *output);
     292  void CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem);
     293  void CreateListOfBondsPerAtom(ofstream *out);
     294
     295  // Graph analysis
     296  MoleculeLeafClass * DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack);
     297  void CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> *BackEdgeStack, int *&MinimumRingSize);
     298  bool PickLocalBackEdges(ofstream *out, atom **ListOfLocalAtoms, class StackClass<bond *> *&ReferenceStack, class StackClass<bond *> *&LocalStack);
     299  bond * FindNextUnused(atom *vertex);
     300  void SetNextComponentNumber(atom *vertex, int nr);
     301  void InitComponentNumbers();
     302  void OutputComponentNumber(ofstream *out, atom *vertex);
     303  void ResetAllBondsToUnused();
     304  void ResetAllAtomNumbers();
     305  int CountCyclicBonds(ofstream *out);
     306  bool CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment);
     307  string GetColor(enum Shading color);
     308
     309  molecule *CopyMolecule();
     310
     311  /// Fragment molecule by two different approaches:
     312  int FragmentMolecule(ofstream *out, int Order, config *configuration);
     313  bool CheckOrderAtSite(ofstream *out, bool *AtomMask, Graph *GlobalKeySetList, int Order, int *MinimumRingSize, char *path = NULL);
     314  bool StoreAdjacencyToFile(ofstream *out, char *path);
     315  bool CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms);
     316  bool ParseOrderAtSiteFromFile(ofstream *out, char *path);
     317  bool StoreOrderAtSiteFile(ofstream *out, char *path);
     318  bool ParseKeySetFile(ofstream *out, char *filename, Graph *&FragmentList);
     319  bool StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path);
     320  bool StoreForcesFile(ofstream *out, MoleculeListClass *BondFragments, char *path, int *SortIndex);
     321  bool CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex);
     322  bool ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet);
     323  void BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem);
     324  /// -# BOSSANOVA
     325  void FragmentBOSSANOVA(ofstream *out, Graph *&FragmentList, KeyStack &RootStack, int *MinimumRingSize);
     326  int PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet);
     327  bool BuildInducedSubgraph(ofstream *out, const molecule *Father);
     328  molecule * StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem);
     329  void SPFragmentGenerator(ofstream *out, struct UniqueFragments *FragmentSearch, int RootDistance, bond **BondsSet, int SetDimension, int SubOrder);
     330  int LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList);
     331  int GuesstimateFragmentCount(ofstream *out, int order);
     332
     333  // Recognize doubly appearing molecules in a list of them
     334  int * IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold);
     335  int * GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule);
     336
     337  // Output routines.
     338  bool Output(ofstream *out);
     339  bool OutputTrajectories(ofstream *out);
     340  void OutputListOfBonds(ofstream *out) const;
     341  bool OutputXYZ(ofstream *out) const;
     342  bool OutputTrajectoriesXYZ(ofstream *out);
     343  bool Checkout(ofstream *out) const;
     344  bool OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output);
     345
     346  private:
     347  int last_atom;      //!< number given to last atom
    333348};
    334349
     
    336351 */
    337352class MoleculeListClass {
    338         public:
    339           MoleculeList ListOfMolecules; //!< List of the contained molecules
    340           int MaxIndex;
    341 
    342         MoleculeListClass();
    343         ~MoleculeListClass();
    344 
    345         bool AddHydrogenCorrection(ofstream *out, char *path);
    346         bool StoreForcesFile(ofstream *out, char *path, int *SortIndex);
    347         bool insert(molecule *mol);
    348         molecule * ReturnIndex(int index);
    349         bool OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex);
    350         int NumberOfActiveMolecules();
    351         void Enumerate(ofstream *out);
    352         void Output(ofstream *out);
    353 
    354         // merging of molecules
     353  public:
     354    MoleculeList ListOfMolecules; //!< List of the contained molecules
     355    int MaxIndex;
     356
     357  MoleculeListClass();
     358  ~MoleculeListClass();
     359
     360  bool AddHydrogenCorrection(ofstream *out, char *path);
     361  bool StoreForcesFile(ofstream *out, char *path, int *SortIndex);
     362  void insert(molecule *mol);
     363  molecule * ReturnIndex(int index);
     364  bool OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex);
     365  int NumberOfActiveMolecules();
     366  void Enumerate(ofstream *out);
     367  void Output(ofstream *out);
     368
     369  // merging of molecules
    355370  bool SimpleMerge(molecule *mol, molecule *srcmol);
    356371  bool SimpleAdd(molecule *mol, molecule *srcmol);
     
    360375  bool EmbedMerge(molecule *mol, molecule *srcmol);
    361376
    362         private:
     377  private:
    363378};
    364379
     
    368383 */
    369384class MoleculeLeafClass {
    370         public:
    371                 molecule *Leaf;                                                                  //!< molecule of this leaf
    372                 //MoleculeLeafClass *UpLeaf;                            //!< Leaf one level up
    373                 //MoleculeLeafClass *DownLeaf;                  //!< First leaf one level down
    374                 MoleculeLeafClass *previous;    //!< Previous leaf on this level
    375                 MoleculeLeafClass *next;                        //!< Next leaf on this level
    376 
    377         //MoleculeLeafClass(MoleculeLeafClass *Up, MoleculeLeafClass *Previous);
    378         MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf);
    379         ~MoleculeLeafClass();
    380 
    381         bool AddLeaf(molecule *ptr, MoleculeLeafClass *Previous);
    382         bool FillBondStructureFromReference(ofstream *out, molecule *reference, int &FragmentCounter, atom ***&ListOfLocalAtoms, bool FreeList = false);
    383         bool FillRootStackForSubgraphs(ofstream *out, KeyStack *&RootStack, bool *AtomMask, int &FragmentCounter);
    384         bool AssignKeySetsToFragment(ofstream *out, molecule *reference, Graph *KeySetList, atom ***&ListOfLocalAtoms, Graph **&FragmentList, int &FragmentCounter, bool FreeList = false);
    385         bool FillListOfLocalAtoms(ofstream *out, atom ***&ListOfLocalAtoms, const int FragmentCounter, const int GlobalAtomCount, bool &FreeList);
    386         void TranslateIndicesToGlobalIDs(ofstream *out, Graph **FragmentList, int &FragmentCounter, int &TotalNumberOfKeySets, Graph &TotalGraph);
    387         int Count() const;
     385  public:
     386    molecule *Leaf;                  //!< molecule of this leaf
     387    //MoleculeLeafClass *UpLeaf;        //!< Leaf one level up
     388    //MoleculeLeafClass *DownLeaf;      //!< First leaf one level down
     389    MoleculeLeafClass *previous;  //!< Previous leaf on this level
     390    MoleculeLeafClass *next;      //!< Next leaf on this level
     391
     392  //MoleculeLeafClass(MoleculeLeafClass *Up, MoleculeLeafClass *Previous);
     393  MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf);
     394  ~MoleculeLeafClass();
     395
     396  bool AddLeaf(molecule *ptr, MoleculeLeafClass *Previous);
     397  bool FillBondStructureFromReference(ofstream *out, molecule *reference, int &FragmentCounter, atom ***&ListOfLocalAtoms, bool FreeList = false);
     398  bool FillRootStackForSubgraphs(ofstream *out, KeyStack *&RootStack, bool *AtomMask, int &FragmentCounter);
     399  bool AssignKeySetsToFragment(ofstream *out, molecule *reference, Graph *KeySetList, atom ***&ListOfLocalAtoms, Graph **&FragmentList, int &FragmentCounter, bool FreeList = false);
     400  bool FillListOfLocalAtoms(ofstream *out, atom ***&ListOfLocalAtoms, const int FragmentCounter, const int GlobalAtomCount, bool &FreeList);
     401  void TranslateIndicesToGlobalIDs(ofstream *out, Graph **FragmentList, int &FragmentCounter, int &TotalNumberOfKeySets, Graph &TotalGraph);
     402  int Count() const;
    388403};
    389404
     
    392407 */
    393408class config {
    394         public:
    395                 int PsiType;
    396                 int MaxPsiDouble;
    397                 int PsiMaxNoUp;
    398                 int PsiMaxNoDown;
    399                 int MaxMinStopStep;
    400                 int InitMaxMinStopStep;
    401                 int ProcPEGamma;
    402                 int ProcPEPsi;
    403                 char *configpath;
    404                 char *configname;
    405                 bool FastParsing;
    406                 double Deltat;
    407                 string basis;
    408 
    409                 private:
    410                 char *mainname;
    411                 char *defaultpath;
    412                 char *pseudopotpath;
    413 
    414                 int DoOutVis;
    415                 int DoOutMes;
    416                 int DoOutNICS;
    417                 int DoOutOrbitals;
    418                 int DoOutCurrent;
    419                 int DoFullCurrent;
    420                 int DoPerturbation;
    421                 int DoWannier;
    422                 int CommonWannier;
    423                 double SawtoothStart;
    424                 int VectorPlane;
    425                 double VectorCut;
    426                 int UseAddGramSch;
    427                 int Seed;
    428 
    429                 int MaxOuterStep;
    430                 int OutVisStep;
    431                 int OutSrcStep;
    432                 double TargetTemp;
    433                 int ScaleTempStep;
    434                 int MaxPsiStep;
    435                 double EpsWannier;
    436 
    437                 int MaxMinStep;
    438                 double RelEpsTotalEnergy;
    439                 double RelEpsKineticEnergy;
    440                 int MaxMinGapStopStep;
    441                 int MaxInitMinStep;
    442                 double InitRelEpsTotalEnergy;
    443                 double InitRelEpsKineticEnergy;
    444                 int InitMaxMinGapStopStep;
    445 
    446                 //double BoxLength[NDIM*NDIM];
    447 
    448                 double ECut;
    449                 int MaxLevel;
    450                 int RiemannTensor;
    451                 int LevRFactor;
    452                 int RiemannLevel;
    453                 int Lev0Factor;
    454                 int RTActualUse;
    455                 int AddPsis;
    456 
    457                 double RCut;
    458                 int StructOpt;
    459                 int IsAngstroem;
    460                 int RelativeCoord;
    461                 int MaxTypes;
    462 
    463 
    464         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);
    465 
    466         public:
    467         config();
    468         ~config();
    469 
    470         int TestSyntax(char *filename, periodentafel *periode, molecule *mol);
    471         void Load(char *filename, periodentafel *periode, molecule *mol);
    472         void LoadOld(char *filename, periodentafel *periode, molecule *mol);
    473         void RetrieveConfigPathAndName(string filename);
    474         bool Save(const char *filename, periodentafel *periode, molecule *mol) const;
    475         bool SaveMPQC(const char *filename, molecule *mol) const;
    476         void Edit();
    477         bool GetIsAngstroem() const;
    478         char *GetDefaultPath() const;
    479         void SetDefaultPath(const char *path);
     409  public:
     410    int PsiType;
     411    int MaxPsiDouble;
     412    int PsiMaxNoUp;
     413    int PsiMaxNoDown;
     414    int MaxMinStopStep;
     415    int InitMaxMinStopStep;
     416    int ProcPEGamma;
     417    int ProcPEPsi;
     418    char *configpath;
     419    char *configname;
     420    bool FastParsing;
     421    double Deltat;
     422    string basis;
     423
     424    int DoConstrainedMD;
     425    int MaxOuterStep;
     426    int Thermostat;
     427    int *ThermostatImplemented;
     428    char **ThermostatNames;
     429    double TempFrequency;
     430    double alpha;
     431    double HooverMass;
     432    double TargetTemp;
     433    int ScaleTempStep;
     434   
     435    private:
     436    char *mainname;
     437    char *defaultpath;
     438    char *pseudopotpath;
     439
     440    int DoOutVis;
     441    int DoOutMes;
     442    int DoOutNICS;
     443    int DoOutOrbitals;
     444    int DoOutCurrent;
     445    int DoFullCurrent;
     446    int DoPerturbation;
     447    int DoWannier;
     448    int CommonWannier;
     449    double SawtoothStart;
     450    int VectorPlane;
     451    double VectorCut;
     452    int UseAddGramSch;
     453    int Seed;
     454
     455    int OutVisStep;
     456    int OutSrcStep;
     457    int MaxPsiStep;
     458    double EpsWannier;
     459
     460    int MaxMinStep;
     461    double RelEpsTotalEnergy;
     462    double RelEpsKineticEnergy;
     463    int MaxMinGapStopStep;
     464    int MaxInitMinStep;
     465    double InitRelEpsTotalEnergy;
     466    double InitRelEpsKineticEnergy;
     467    int InitMaxMinGapStopStep;
     468
     469    //double BoxLength[NDIM*NDIM];
     470
     471    double ECut;
     472    int MaxLevel;
     473    int RiemannTensor;
     474    int LevRFactor;
     475    int RiemannLevel;
     476    int Lev0Factor;
     477    int RTActualUse;
     478    int AddPsis;
     479
     480    double RCut;
     481    int StructOpt;
     482    int IsAngstroem;
     483    int RelativeCoord;
     484    int MaxTypes;
     485
     486
     487  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);
     488
     489  public:
     490  config();
     491  ~config();
     492
     493  int TestSyntax(char *filename, periodentafel *periode, molecule *mol);
     494  void Load(char *filename, periodentafel *periode, molecule *mol);
     495  void LoadOld(char *filename, periodentafel *periode, molecule *mol);
     496  void RetrieveConfigPathAndName(string filename);
     497  bool Save(const char *filename, periodentafel *periode, molecule *mol) const;
     498  bool SaveMPQC(const char *filename, molecule *mol) const;
     499  void Edit();
     500  bool GetIsAngstroem() const;
     501  char *GetDefaultPath() const;
     502  void SetDefaultPath(const char *path);
     503  void InitThermostats(ifstream *source);
    480504};
    481505
  • src/parser.cpp

    r375b458 r51c910  
    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)*1, "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  ColumnCounter = (int *) Malloc(sizeof(int)*(1), "MatrixContainer::MatrixContainer: *ColumnCounter");
     62  Header[0] = NULL;
     63  Matrix[0] = NULL;
     64  RowCounter[0] = -1;
     65  MatrixCounter = 0;
     66  ColumnCounter[0] = -1;
    6567};
    6668
     
    6870 */
    6971MatrixContainer::~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");
    93 };
    94 
     72  if (Matrix != NULL) {
     73    for(int i=MatrixCounter;i--;) {
     74      if ((ColumnCounter != NULL) && (RowCounter != NULL)) {
     75          for(int j=RowCounter[i]+1;j--;)
     76            Free((void **)&Matrix[i][j], "MatrixContainer::~MatrixContainer: *Matrix[][]");
     77        Free((void **)&Matrix[i], "MatrixContainer::~MatrixContainer: **Matrix[]");
     78      }
     79    }
     80    if ((ColumnCounter != NULL) && (RowCounter != NULL) && (Matrix[MatrixCounter] != NULL))
     81      for(int j=RowCounter[MatrixCounter]+1;j--;)
     82        Free((void **)&Matrix[MatrixCounter][j], "MatrixContainer::~MatrixContainer: *Matrix[MatrixCounter][]");
     83    if (MatrixCounter != 0)
     84      Free((void **)&Matrix[MatrixCounter], "MatrixContainer::~MatrixContainer: **Matrix[MatrixCounter]");
     85    Free((void **)&Matrix, "MatrixContainer::~MatrixContainer: ***Matrix");
     86  }
     87  if (Indices != NULL)
     88    for(int i=MatrixCounter+1;i--;) {
     89      Free((void **)&Indices[i], "MatrixContainer::~MatrixContainer: *Indices[]");
     90    }
     91  Free((void **)&Indices, "MatrixContainer::~MatrixContainer: **Indices");
     92 
     93  if (Header != NULL)
     94    for(int i=MatrixCounter+1;i--;)
     95      Free((void **)&Header[i], "MatrixContainer::~MatrixContainer: *Header[]");
     96  Free((void **)&Header, "MatrixContainer::~MatrixContainer: **Header");
     97  Free((void **)&RowCounter, "MatrixContainer::~MatrixContainer: *RowCounter");
     98  Free((void **)&ColumnCounter, "MatrixContainer::~MatrixContainer: *RowCounter");
     99};
     100
     101/** Either copies index matrix from another MatrixContainer or initialises with trivial mapping if NULL.
     102 * This either copies the index matrix or just maps 1 to 1, 2 to 2 and so on for all fragments.
     103 * \param *Matrix pointer to other MatrixContainer
     104 * \return true - copy/initialisation sucessful, false - dimension false for copying
     105 */
     106bool MatrixContainer::InitialiseIndices(class MatrixContainer *Matrix)
     107{
     108  cout << "Initialising indices";
     109  if (Matrix == NULL) {
     110    cout << " with trivial mapping." << endl;
     111    Indices = (int **) Malloc(sizeof(int *)*(MatrixCounter+1), "MatrixContainer::InitialiseIndices: **Indices");
     112    for(int i=MatrixCounter+1;i--;) {
     113      Indices[i] = (int *) Malloc(sizeof(int)*RowCounter[i], "MatrixContainer::InitialiseIndices: *Indices[]");
     114      for(int j=RowCounter[i];j--;)
     115        Indices[i][j] = j;
     116    }
     117  } else {
     118    cout << " from other MatrixContainer." << endl;
     119    if (MatrixCounter != Matrix->MatrixCounter)
     120      return false;
     121    Indices = (int **) Malloc(sizeof(int *)*(MatrixCounter+1), "MatrixContainer::InitialiseIndices: **Indices");
     122    for(int i=MatrixCounter+1;i--;) {
     123      if (RowCounter[i] != Matrix->RowCounter[i])
     124        return false;
     125      Indices[i] = (int *) Malloc(sizeof(int)*Matrix->RowCounter[i], "MatrixContainer::InitialiseIndices: *Indices[]");
     126      for(int j=Matrix->RowCounter[i];j--;) {
     127        Indices[i][j] = Matrix->Indices[i][j];
     128        //cout << Indices[i][j] << "\t";
     129      }
     130      //cout << endl;
     131    }
     132  }
     133  return true;
     134};
    95135
    96136/** 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
     137 *    -# open the matrix file
     138 *    -# skip some lines (\a skiplines)
     139 *    -# scan header lines for number of columns
     140 *    -# scan lines for number of rows
     141 *    -# allocate matrix
     142 *    -# loop over found column and row counts and parse in each entry
    103143 * \param *name directory with files
    104144 * \param skiplines number of inital lines to skip
     
    109149bool MatrixContainer::ParseMatrix(const char *name, int skiplines, int skipcolumns, int MatrixNr)
    110150{
    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;
     151  ifstream input;
     152  stringstream line;
     153  string token;
     154  char filename[1023];
     155
     156  input.open(name, ios::in);
     157  //cout << "Opening " << name << " ... "  << input << endl;
     158  if (input == NULL) {
     159    cerr << endl << "Unable to open " << name << ", is the directory correct?" << endl;
     160    return false;
     161  }
     162
     163  // parse header
     164  Header[MatrixNr] = (char *) Malloc(sizeof(char)*1024, "MatrixContainer::ParseMatrix: *Header[]");
     165  for (int m=skiplines+1;m--;)
     166    input.getline(Header[MatrixNr], 1023);
     167 
     168  // scan header for number of columns
     169  line.str(Header[MatrixNr]);
     170  for(int k=skipcolumns;k--;)
     171    line >> Header[MatrixNr];
     172  //cout << line.str() << endl;
     173  ColumnCounter[MatrixNr]=0;
     174  while ( getline(line,token, '\t') ) {
     175    if (token.length() > 0)
     176      ColumnCounter[MatrixNr]++;
     177  }
     178  //cout << line.str() << endl;
     179  //cout << "ColumnCounter[" << MatrixNr << "]: " << ColumnCounter[MatrixNr] << "." << endl;
     180  if (ColumnCounter[MatrixNr] == 0)
     181    cerr << "ColumnCounter[" << MatrixNr << "]: " << ColumnCounter[MatrixNr] << " from file " << name << ", this is probably an error!" << endl;
     182 
     183  // scan rest for number of rows/lines
     184  RowCounter[MatrixNr]=-1;    // counts one line too much
     185  while (!input.eof()) {
     186    input.getline(filename, 1023);
     187    //cout << "Comparing: " << strncmp(filename,"MeanForce",9) << endl;
     188    RowCounter[MatrixNr]++; // then line was not last MeanForce
     189    if (strncmp(filename,"MeanForce", 9) == 0) {
     190      break;
     191    }
     192  }
     193  //cout << "RowCounter[" << MatrixNr << "]: " << RowCounter[MatrixNr] << " from file " << name << "." << endl;
     194  if (RowCounter[MatrixNr] == 0)
     195    cerr << "RowCounter[" << MatrixNr << "]: " << RowCounter[MatrixNr] << " from file " << name << ", this is probably an error!" << endl;
     196
     197  // allocate matrix if it's not zero dimension in one direction
     198  if ((ColumnCounter[MatrixNr] > 0) && (RowCounter[MatrixNr] > -1)) {
     199    Matrix[MatrixNr] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixNr]+1), "MatrixContainer::ParseMatrix: **Matrix[]");
     200 
     201    // parse in each entry for this matrix
     202    input.clear();
     203    input.seekg(ios::beg);
     204    for (int m=skiplines+1;m--;)
     205      input.getline(Header[MatrixNr], 1023);    // skip header
     206    line.str(Header[MatrixNr]);
     207    for(int k=skipcolumns;k--;)  // skip columns in header too
     208      line >> filename;
     209    strncpy(Header[MatrixNr], line.str().c_str(), 1023); 
     210    for(int j=0;j<RowCounter[MatrixNr];j++) {
     211      Matrix[MatrixNr][j] = (double *) Malloc(sizeof(double)*ColumnCounter[MatrixNr], "MatrixContainer::ParseMatrix: *Matrix[][]");
     212      input.getline(filename, 1023);
     213      stringstream lines(filename);
     214      //cout << "Matrix at level " << j << ":";// << filename << endl;
     215      for(int k=skipcolumns;k--;)
     216        lines >> filename;
     217      for(int k=0;(k<ColumnCounter[MatrixNr]) && (!lines.eof());k++) {
     218        lines >> Matrix[MatrixNr][j][k];
     219        //cout << " " << setprecision(2) << Matrix[MatrixNr][j][k];;
     220      }
     221      //cout << endl;
     222      Matrix[MatrixNr][ RowCounter[MatrixNr] ] = (double *) Malloc(sizeof(double)*ColumnCounter[MatrixNr], "MatrixContainer::ParseMatrix: *Matrix[RowCounter[MatrixNr]][]");
     223      for(int j=ColumnCounter[MatrixNr];j--;)
     224        Matrix[MatrixNr][ RowCounter[MatrixNr] ][j] = 0.;
     225    }
     226  } else {
     227    cerr << "ERROR: Matrix nr. " << MatrixNr << " has column and row count of (" << ColumnCounter[MatrixNr] << "," << RowCounter[MatrixNr] << "), could not allocate nor parse!" << endl;
     228  }
     229  input.close();
     230  return true;
    190231};
    191232
     
    193234 * -# First, count the number of matrices by counting lines in KEYSETFILE
    194235 * -# 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
     236 *    -# construct the fragment number
     237 *    -# open the matrix file
     238 *    -# skip some lines (\a skiplines)
     239 *    -# scan header lines for number of columns
     240 *    -# scan lines for number of rows
     241 *    -# allocate matrix
     242 *    -# loop over found column and row counts and parse in each entry
    202243 * -# Finally, allocate one additional matrix (\a MatrixCounter) containing combined or temporary values
    203244 * \param *name directory with files
     
    210251bool MatrixContainer::ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns)
    211252{
    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;
     253  char filename[1023];
     254  ifstream input;
     255  char *FragmentNumber = NULL;
     256  stringstream file;
     257  string token;
     258
     259  // count the number of matrices
     260  MatrixCounter = -1; // we count one too much
     261  file << name << FRAGMENTPREFIX << KEYSETFILE;
     262  input.open(file.str().c_str(), ios::in);
     263  if (input == NULL) {
     264    cout << endl << "Unable to open " << file.str() << ", is the directory correct?" << endl;
     265    return false;
     266  }
     267  while (!input.eof()) {
     268    input.getline(filename, 1023);
     269    stringstream zeile(filename);
     270    MatrixCounter++;
     271  }
     272  input.close();
     273  cout << "Determined " << MatrixCounter << " fragments." << endl;
     274
     275  cout << "Parsing through each fragment and retrieving " << prefix << suffix << "." << endl;
     276  Header = (char **) ReAlloc(Header, sizeof(char *)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: **Header"); // one more each for the total molecule
     277  Matrix = (double ***) ReAlloc(Matrix, sizeof(double **)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: ***Matrix"); // one more each for the total molecule
     278  RowCounter = (int *) ReAlloc(RowCounter, sizeof(int)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: *RowCounter");
     279  ColumnCounter = (int *) ReAlloc(ColumnCounter, sizeof(int)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: *ColumnCounter");
     280  for(int i=MatrixCounter+1;i--;) {
     281    Matrix[i] = NULL;
     282    Header[i] = NULL;
     283    RowCounter[i] = -1;
     284    ColumnCounter[i] = -1;
     285  }
     286  for(int i=0; i < MatrixCounter;i++) {
     287    // open matrix file
     288    FragmentNumber = FixedDigitNumber(MatrixCounter, i);
     289    file.str(" ");
     290    file << name << FRAGMENTPREFIX << FragmentNumber << prefix << suffix;
     291    if (!ParseMatrix(file.str().c_str(), skiplines, skipcolumns, i))
     292      return false;
     293    Free((void **)&FragmentNumber, "MatrixContainer::ParseFragmentMatrix: *FragmentNumber");
     294  }
     295  return true;
    251296};
    252297
    253298/** Allocates and resets the memory for a number \a MCounter of matrices.
    254  * \param *GivenHeader Header line
     299 * \param **GivenHeader Header line for each matrix
    255300 * \param MCounter number of matrices
    256301 * \param *RCounter number of rows for each matrix
    257  * \param CCounter number of columns for all matrices
    258  * \return Allocation successful
    259  */
    260 bool MatrixContainer::AllocateMatrix(char *GivenHeader, int MCounter, int *RCounter, int CCounter)
    261 {
    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;
     302 * \param *CCounter number of columns for each matrix
     303 * \return Allocation successful
     304 */
     305bool MatrixContainer::AllocateMatrix(char **GivenHeader, int MCounter, int *RCounter, int *CCounter)
     306{
     307  MatrixCounter = MCounter;
     308  Header = (char **) Malloc(sizeof(char *)*(MatrixCounter+1), "MatrixContainer::AllocateMatrix: *Header");
     309  Matrix = (double ***) Malloc(sizeof(double **)*(MatrixCounter+1), "MatrixContainer::AllocateMatrix: ***Matrix"); // one more each for the total molecule
     310  RowCounter = (int *) Malloc(sizeof(int)*(MatrixCounter+1), "MatrixContainer::AllocateMatrix: *RowCounter");
     311  ColumnCounter = (int *) Malloc(sizeof(int)*(MatrixCounter+1), "MatrixContainer::AllocateMatrix: *ColumnCounter");
     312  for(int i=MatrixCounter+1;i--;) {
     313    Header[i] = (char *) Malloc(sizeof(char)*1024, "MatrixContainer::AllocateMatrix: *Header[i]");
     314    strncpy(Header[i], GivenHeader[i], 1023);
     315    RowCounter[i] = RCounter[i];
     316    ColumnCounter[i] = CCounter[i];
     317    Matrix[i] = (double **) Malloc(sizeof(double *)*(RowCounter[i]+1), "MatrixContainer::AllocateMatrix: **Matrix[]"); 
     318    for(int j=RowCounter[i]+1;j--;) {
     319      Matrix[i][j] = (double *) Malloc(sizeof(double)*ColumnCounter[i], "MatrixContainer::AllocateMatrix: *Matrix[][]");
     320      for(int k=ColumnCounter[i];k--;)
     321        Matrix[i][j][k] = 0.;
     322    }
     323  }
     324  return true;
    279325};
    280326
     
    284330bool MatrixContainer::ResetMatrix()
    285331{
    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;
     332  for(int i=MatrixCounter+1;i--;)
     333    for(int j=RowCounter[i]+1;j--;)
     334      for(int k=ColumnCounter[i];k--;)
     335        Matrix[i][j][k] = 0.;
     336  return true;
    291337};
    292338
     
    296342double MatrixContainer::FindMaxValue()
    297343{
    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;
     344  double max = Matrix[0][0][0];
     345  for(int i=MatrixCounter+1;i--;)
     346    for(int j=RowCounter[i]+1;j--;)
     347      for(int k=ColumnCounter[i];k--;)
     348        if (fabs(Matrix[i][j][k]) > max)
     349          max = fabs(Matrix[i][j][k]);
     350  if (fabs(max) < MYEPSILON)
     351    max += MYEPSILON;
    306352 return max;
    307353};
     
    312358double MatrixContainer::FindMinValue()
    313359{
    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;
     360  double min = Matrix[0][0][0];
     361  for(int i=MatrixCounter+1;i--;)
     362    for(int j=RowCounter[i]+1;j--;)
     363      for(int k=ColumnCounter[i];k--;)
     364        if (fabs(Matrix[i][j][k]) < min)
     365          min = fabs(Matrix[i][j][k]);
     366  if (fabs(min) < MYEPSILON)
     367    min += MYEPSILON;
     368  return min;
    323369};
    324370
     
    330376bool MatrixContainer::SetLastMatrix(double value, int skipcolumns)
    331377{
    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;
     378  for(int j=RowCounter[MatrixCounter]+1;j--;)
     379    for(int k=skipcolumns;k<ColumnCounter[MatrixCounter];k++)
     380      Matrix[MatrixCounter][j][k] = value;
     381  return true;
    336382};
    337383
     
    343389bool MatrixContainer::SetLastMatrix(double **values, int skipcolumns)
    344390{
    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;
    349 };
    350 
    351 /** Sums the energy with each factor and put into last element of \a ***Energies.
     391  for(int j=RowCounter[MatrixCounter]+1;j--;)
     392    for(int k=skipcolumns;k<ColumnCounter[MatrixCounter];k++)
     393      Matrix[MatrixCounter][j][k] = values[j][k];
     394  return true;
     395};
     396
     397/** Sums the entries with each factor and put into last element of \a ***Matrix.
    352398 * Sums over "E"-terms to create the "F"-terms
    353  * \param Matrix MatrixContainer with matrices (LevelCounter by ColumnCounter) with all the energies.
     399 * \param Matrix MatrixContainer with matrices (LevelCounter by *ColumnCounter) with all the energies.
    354400 * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order
    355401 * \param Order bond order
     
    358404bool MatrixContainer::SumSubManyBodyTerms(class MatrixContainer &MatrixValues, class KeySetsContainer &KeySet, int Order)
    359405{
    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;
     406  // go through each order
     407  for (int CurrentFragment=0;CurrentFragment<KeySet.FragmentsPerOrder[Order];CurrentFragment++) {
     408    //cout << "Current Fragment is " << CurrentFragment << "/" << KeySet.OrderSet[Order][CurrentFragment] << "." << endl;
     409    // then go per order through each suborder and pick together all the terms that contain this fragment
     410    for(int SubOrder=0;SubOrder<=Order;SubOrder++) { // go through all suborders up to the desired order
     411      for (int j=0;j<KeySet.FragmentsPerOrder[SubOrder];j++) { // go through all possible fragments of size suborder
     412        if (KeySet.Contains(KeySet.OrderSet[Order][CurrentFragment], KeySet.OrderSet[SubOrder][j])) {
     413          //cout << "Current other fragment is " << j << "/" << KeySet.OrderSet[SubOrder][j] << "." << endl;
     414          // if the fragment's indices are all in the current fragment
     415          for(int k=0;k<RowCounter[ KeySet.OrderSet[SubOrder][j] ];k++) { // go through all atoms in this fragment
     416            int m = MatrixValues.Indices[ KeySet.OrderSet[SubOrder][j] ][k];
     417            //cout << "Current index is " << k << "/" << m << "." << endl;
     418            if (m != -1) { // if it's not an added hydrogen
     419              for (int l=0;l<RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ];l++) { // look for the corresponding index in the current fragment
     420                //cout << "Comparing " << m << " with " << MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][l] << "." << endl;
     421                if (m == MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][l]) {
     422                  m = l;
     423                  break;
     424                }
     425              }
     426              //cout << "Corresponding index in CurrentFragment is " << m << "." << endl;
     427              if (m > RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ]) {
     428                cerr << "In fragment No. " << KeySet.OrderSet[Order][CurrentFragment]  << " current force index " << m << " is greater than " << RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ] << "!" << endl;
     429                return false;
     430              }
     431              if (Order == SubOrder) { // equal order is always copy from Energies
     432                for(int l=ColumnCounter[ KeySet.OrderSet[SubOrder][j] ];l--;) // then adds/subtract each column
     433                  Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][l] += MatrixValues.Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l];
     434              } else {
     435                for(int l=ColumnCounter[ KeySet.OrderSet[SubOrder][j] ];l--;)
     436                  Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][l] -= Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l];
     437              }
     438            }
     439            //if ((ColumnCounter[ KeySet.OrderSet[SubOrder][j] ]>1) && (RowCounter[0]-1 >= 1))
     440             //cout << "Fragments[ KeySet.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySet.OrderSet[Order][CurrentFragment] << " ][" << RowCounter[0]-1 << "][" << 1 << "] = " <<  Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][RowCounter[0]-1][1] << endl;
     441          }
     442        } else {
     443          //cout << "Fragment " << KeySet.OrderSet[SubOrder][j] << " is not contained in fragment " << KeySet.OrderSet[Order][CurrentFragment] << "." << endl;
     444        }
     445      }
     446    }
     447   //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;
     448  }
     449
     450  return true;
    405451};
    406452
     
    412458bool MatrixContainer::WriteTotalFragments(const char *name, const char *prefix)
    413459{
    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;
     460  ofstream output;
     461  char *FragmentNumber = NULL;
     462
     463  cout << "Writing fragment files." << endl;
     464  for(int i=0;i<MatrixCounter;i++) {
     465    stringstream line;
     466    FragmentNumber = FixedDigitNumber(MatrixCounter, i);
     467    line << name << FRAGMENTPREFIX << FragmentNumber << "/" << prefix;
     468    Free((void **)&FragmentNumber, "*FragmentNumber");
     469    output.open(line.str().c_str(), ios::out);
     470    if (output == NULL) {
     471      cerr << "Unable to open output energy file " << line.str() << "!" << endl;
     472      return false;
     473    }
     474    output << Header[i] << endl;
     475    for(int j=0;j<RowCounter[i];j++) {
     476      for(int k=0;k<ColumnCounter[i];k++)
     477        output << scientific << Matrix[i][j][k] << "\t";
     478      output << endl;
     479    }
     480    output.close();
     481  }
     482  return true;
    437483};
    438484
     
    445491bool MatrixContainer::WriteLastMatrix(const char *name, const char *prefix, const char *suffix)
    446492{
    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;
     493  ofstream output;
     494  stringstream line;
     495
     496  cout << "Writing matrix values of " << suffix << "." << endl;
     497  line << name << prefix << suffix;
     498  output.open(line.str().c_str(), ios::out);
     499  if (output == NULL) {
     500    cerr << "Unable to open output matrix file " << line.str() << "!" << endl;
     501    return false;
     502  }
     503  output << Header[MatrixCounter] << endl;
     504  for(int j=0;j<RowCounter[MatrixCounter];j++) {
     505    for(int k=0;k<ColumnCounter[MatrixCounter];k++)
     506      output << scientific << Matrix[MatrixCounter][j][k] << "\t";
     507    output << endl;
     508  }
     509  output.close();
     510  return true;
    465511};
    466512
     
    473519bool EnergyMatrix::ParseIndices()
    474520{
    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;
     521  cout << "Parsing energy indices." << endl;
     522  Indices = (int **) Malloc(sizeof(int *)*(MatrixCounter+1), "EnergyMatrix::ParseIndices: **Indices");
     523  for(int i=MatrixCounter+1;i--;) {
     524    Indices[i] = (int *) Malloc(sizeof(int)*RowCounter[i], "EnergyMatrix::ParseIndices: *Indices[]");
     525    for(int j=RowCounter[i];j--;)
     526      Indices[i][j] = j;
     527  }
     528  return true;
    483529};
    484530
    485531/** Sums the energy with each factor and put into last element of \a EnergyMatrix::Matrix.
    486532 * Sums over the "F"-terms in ANOVA decomposition.
    487  * \param Matrix MatrixContainer with matrices (LevelCounter by ColumnCounter) with all the energies.
     533 * \param Matrix MatrixContainer with matrices (LevelCounter by *ColumnCounter) with all the energies.
    488534 * \param CorrectionFragments MatrixContainer with hydrogen saturation correction per fragments
    489535 * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order
     
    494540bool EnergyMatrix::SumSubEnergy(class EnergyMatrix &Fragments, class EnergyMatrix *CorrectionFragments, class KeySetsContainer &KeySet, int Order, double sign)
    495541{
    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;
     542  // sum energy
     543  if (CorrectionFragments == NULL)
     544    for(int i=KeySet.FragmentsPerOrder[Order];i--;)
     545      for(int j=RowCounter[ KeySet.OrderSet[Order][i] ];j--;)
     546        for(int k=ColumnCounter[ KeySet.OrderSet[Order][i] ];k--;)
     547          Matrix[MatrixCounter][j][k] += sign*Fragments.Matrix[ KeySet.OrderSet[Order][i] ][j][k];
     548  else
     549    for(int i=KeySet.FragmentsPerOrder[Order];i--;)
     550      for(int j=RowCounter[ KeySet.OrderSet[Order][i] ];j--;)
     551        for(int k=ColumnCounter[ KeySet.OrderSet[Order][i] ];k--;)
     552          Matrix[MatrixCounter][j][k] += sign*(Fragments.Matrix[ KeySet.OrderSet[Order][i] ][j][k] + CorrectionFragments->Matrix[ KeySet.OrderSet[Order][i] ][j][k]);
     553  return true;
    508554};
    509555
     
    518564bool EnergyMatrix::ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns)
    519565{
    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;
     566  char filename[1024];
     567  bool status = MatrixContainer::ParseFragmentMatrix(name, prefix, suffix, skiplines, skipcolumns);
     568
     569  if (status) {
     570    // count maximum of columns
     571    RowCounter[MatrixCounter] = 0;
     572    ColumnCounter[MatrixCounter] = 0;
     573    for(int j=0; j < MatrixCounter;j++) { // (energy matrix might be bigger than number of atoms in terms of rows)
     574      if (RowCounter[j] > RowCounter[MatrixCounter])
     575        RowCounter[MatrixCounter] = RowCounter[j];
     576      if (ColumnCounter[j] > ColumnCounter[MatrixCounter])  // take maximum of all for last matrix
     577        ColumnCounter[MatrixCounter] = ColumnCounter[j];
     578    }
     579    // allocate last plus one matrix
     580    cout << "Allocating last plus one matrix with " << (RowCounter[MatrixCounter]+1) << " rows and " << ColumnCounter[MatrixCounter] << " columns." << endl;
     581    Matrix[MatrixCounter] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixCounter]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]");
     582    for(int j=0;j<=RowCounter[MatrixCounter];j++)
     583      Matrix[MatrixCounter][j] = (double *) Malloc(sizeof(double)*ColumnCounter[MatrixCounter], "MatrixContainer::ParseFragmentMatrix: *Matrix[][]");
     584   
     585    // try independently to parse global energysuffix file if present
     586    strncpy(filename, name, 1023);
     587    strncat(filename, prefix, 1023-strlen(filename));
     588    strncat(filename, suffix.c_str(), 1023-strlen(filename));
     589    ParseMatrix(filename, skiplines, skipcolumns, MatrixCounter);
     590  }
     591  return status;
    542592};
    543593
     
    550600bool ForceMatrix::ParseIndices(char *name)
    551601{
    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;
     602  ifstream input;
     603  char *FragmentNumber = NULL;
     604  char filename[1023];
     605  stringstream line;
     606
     607  cout << "Parsing force indices for " << MatrixCounter << " matrices." << endl;
     608  Indices = (int **) Malloc(sizeof(int *)*(MatrixCounter+1), "ForceMatrix::ParseIndices: **Indices");
     609  line << name << FRAGMENTPREFIX << FORCESFILE;
     610  input.open(line.str().c_str(), ios::in);
     611  //cout << "Opening " << line.str() << " ... "  << input << endl;
     612  if (input == NULL) {
     613    cout << endl << "Unable to open " << line.str() << ", is the directory correct?" << endl;
     614    return false;
     615  }
     616  for (int i=0;(i<MatrixCounter) && (!input.eof());i++) {
     617    // get the number of atoms for this fragment
     618    input.getline(filename, 1023);
     619    line.str(filename);
     620    // parse the values
     621    Indices[i] = (int *) Malloc(sizeof(int)*RowCounter[i], "ForceMatrix::ParseIndices: *Indices[]");
     622    FragmentNumber = FixedDigitNumber(MatrixCounter, i);
     623    //cout << FRAGMENTPREFIX << FragmentNumber << "[" << RowCounter[i] << "]:";
     624    Free((void **)&FragmentNumber, "ForceMatrix::ParseIndices: *FragmentNumber");
     625    for(int j=0;(j<RowCounter[i]) && (!line.eof());j++) {
     626      line >> Indices[i][j];
     627      //cout << " " << Indices[i][j];
     628    }
     629    //cout << endl;
     630  }
     631  Indices[MatrixCounter] = (int *) Malloc(sizeof(int)*RowCounter[MatrixCounter], "ForceMatrix::ParseIndices: *Indices[]");
     632  for(int j=RowCounter[MatrixCounter];j--;) {
     633    Indices[MatrixCounter][j] = j;
     634  }
     635  input.close();
     636  return true;
    587637};
    588638
    589639
    590640/** Sums the forces and puts into last element of \a ForceMatrix::Matrix.
    591  * \param Matrix MatrixContainer with matrices (LevelCounter by ColumnCounter) with all the energies.
     641 * \param Matrix MatrixContainer with matrices (LevelCounter by *ColumnCounter) with all the energies.
    592642 * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order
    593643 * \param Order bond order
    594  *      \param sign +1 or -1
     644 *  \param sign +1 or -1
    595645 * \return true if summing was successful
    596646 */
    597647bool ForceMatrix::SumSubForces(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign)
    598648{
    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;
     649  int FragmentNr;
     650  // sum forces
     651  for(int i=0;i<KeySet.FragmentsPerOrder[Order];i++) {
     652    FragmentNr = KeySet.OrderSet[Order][i];
     653    for(int l=0;l<RowCounter[ FragmentNr ];l++) {
     654      int j = Indices[ FragmentNr ][l];
     655      if (j > RowCounter[MatrixCounter]) {
     656        cerr << "Current force index " << j << " is greater than " << RowCounter[MatrixCounter] << "!" << endl;
     657        return false;
     658      }
     659      if (j != -1) {
     660        //if (j == 0) cout << "Summing onto ion 0, type 0 from fragment " << FragmentNr << ", ion " << l << "." << endl;
     661        for(int k=2;k<ColumnCounter[MatrixCounter];k++)
     662          Matrix[MatrixCounter][j][k] += sign*Fragments.Matrix[ FragmentNr ][l][k];
     663      }
     664    }
     665  }
     666  return true;
    617667};
    618668
     
    628678bool ForceMatrix::ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns)
    629679{
    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;
     680  char filename[1023];
     681  ifstream input;
     682  stringstream file;
     683  int nr;
     684  bool status = MatrixContainer::ParseFragmentMatrix(name, prefix, suffix, skiplines, skipcolumns);
     685
     686  if (status) {
     687    // count number of atoms for last plus one matrix
     688    file << name << FRAGMENTPREFIX << KEYSETFILE;
     689    input.open(file.str().c_str(), ios::in);
     690    if (input == NULL) {
     691      cout << endl << "Unable to open " << file.str() << ", is the directory correct?" << endl;
     692      return false;
     693    }
     694    RowCounter[MatrixCounter] = 0;
     695    while (!input.eof()) {
     696      input.getline(filename, 1023);
     697      stringstream zeile(filename);
     698      while (!zeile.eof()) {
     699        zeile >> nr;
     700        //cout << "Current index: " << nr << "." << endl;
     701        if (nr > RowCounter[MatrixCounter])
     702          RowCounter[MatrixCounter] = nr;
     703      }
     704    }
     705    RowCounter[MatrixCounter]++;    // nr start at 0, count starts at 1
     706    input.close();
     707
     708    ColumnCounter[MatrixCounter] = 0;
     709    for(int j=0; j < MatrixCounter;j++) { // (energy matrix might be bigger than number of atoms in terms of rows)
     710      if (ColumnCounter[j] > ColumnCounter[MatrixCounter])  // take maximum of all for last matrix
     711        ColumnCounter[MatrixCounter] = ColumnCounter[j];
     712    }
     713 
     714    // allocate last plus one matrix
     715    cout << "Allocating last plus one matrix with " << (RowCounter[MatrixCounter]+1) << " rows and " << ColumnCounter[MatrixCounter] << " columns." << endl;
     716    Matrix[MatrixCounter] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixCounter]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]");
     717    for(int j=0;j<=RowCounter[MatrixCounter];j++)
     718      Matrix[MatrixCounter][j] = (double *) Malloc(sizeof(double)*ColumnCounter[MatrixCounter], "MatrixContainer::ParseFragmentMatrix: *Matrix[][]");
     719
     720    // try independently to parse global forcesuffix file if present
     721    strncpy(filename, name, 1023);
     722    strncat(filename, prefix, 1023-strlen(filename));
     723    strncat(filename, suffix.c_str(), 1023-strlen(filename));
     724    ParseMatrix(filename, skiplines, skipcolumns, MatrixCounter);
     725  }
     726 
     727
     728  return status;
     729};
     730
     731// ======================================= CLASS HessianMatrix =============================
     732
     733/** Parsing force Indices of each fragment
     734 * \param *name directory with \a ForcesFile
     735 * \return parsing successful
     736 */
     737bool HessianMatrix::ParseIndices(char *name)
     738{
     739  ifstream input;
     740  char *FragmentNumber = NULL;
     741  char filename[1023];
     742  stringstream line;
     743 
     744  cout << "Parsing hessian indices for " << MatrixCounter << " matrices." << endl;
     745  Indices = (int **) Malloc(sizeof(int *)*(MatrixCounter+1), "HessianMatrix::ParseIndices: **Indices");
     746  line << name << FRAGMENTPREFIX << FORCESFILE;
     747  input.open(line.str().c_str(), ios::in);
     748  //cout << "Opening " << line.str() << " ... "  << input << endl;
     749  if (input == NULL) {
     750    cout << endl << "Unable to open " << line.str() << ", is the directory correct?" << endl;
     751    return false;
     752  }
     753  for (int i=0;(i<MatrixCounter) && (!input.eof());i++) {
     754    // get the number of atoms for this fragment
     755    input.getline(filename, 1023);
     756    line.str(filename);
     757    // parse the values
     758    Indices[i] = (int *) Malloc(sizeof(int)*RowCounter[i], "HessianMatrix::ParseIndices: *Indices[]");
     759    FragmentNumber = FixedDigitNumber(MatrixCounter, i);
     760    //cout << FRAGMENTPREFIX << FragmentNumber << "[" << RowCounter[i] << "]:";
     761    Free((void **)&FragmentNumber, "HessianMatrix::ParseIndices: *FragmentNumber");
     762    for(int j=0;(j<RowCounter[i]) && (!line.eof());j++) {
     763      line >> Indices[i][j];
     764      //cout << " " << Indices[i][j];
     765    }
     766    //cout << endl;
     767  }
     768  Indices[MatrixCounter] = (int *) Malloc(sizeof(int)*RowCounter[MatrixCounter], "HessianMatrix::ParseIndices: *Indices[]");
     769  for(int j=RowCounter[MatrixCounter];j--;) {
     770    Indices[MatrixCounter][j] = j;
     771  }
     772  input.close();
     773  return true;
     774};
     775
     776
     777/** Sums the hessian entries and puts into last element of \a HessianMatrix::Matrix.
     778 * \param Matrix MatrixContainer with matrices (LevelCounter by *ColumnCounter) with all the energies.
     779 * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order
     780 * \param Order bond order
     781 *  \param sign +1 or -1
     782 * \return true if summing was successful
     783 */
     784bool HessianMatrix::SumSubHessians(class HessianMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign)
     785{
     786  int FragmentNr;
     787  // sum forces
     788  for(int i=0;i<KeySet.FragmentsPerOrder[Order];i++) {
     789    FragmentNr = KeySet.OrderSet[Order][i];
     790    for(int l=0;l<RowCounter[ FragmentNr ];l++) {
     791      int j = Indices[ FragmentNr ][l];
     792      if (j > RowCounter[MatrixCounter]) {
     793        cerr << "Current hessian index " << j << " is greater than " << RowCounter[MatrixCounter] << ", where i=" << i << ", Order=" << Order << ", l=" << l << " and FragmentNr=" << FragmentNr << "!" << endl;
     794        return false;
     795      }
     796      if (j != -1) {
     797        for(int m=0;m<ColumnCounter[ FragmentNr ];m++) {
     798          int k = Indices[ FragmentNr ][m];
     799          if (k > ColumnCounter[MatrixCounter]) {
     800            cerr << "Current hessian index " << k << " is greater than " << ColumnCounter[MatrixCounter] << ", where m=" << m << ", j=" << j << ", i=" << i << ", Order=" << Order << ", l=" << l << " and FragmentNr=" << FragmentNr << "!" << endl;
     801            return false;
     802          }
     803          if (k != -1) {
     804            //cout << "Adding " << sign*Fragments.Matrix[ FragmentNr ][l][m] << " from [" << l << "][" << m << "] onto [" << j << "][" << k << "]." << endl;
     805            Matrix[MatrixCounter][j][k] += sign*Fragments.Matrix[ FragmentNr ][l][m];
     806          }
     807        }
     808      }
     809    }
     810  }
     811  return true;
     812};
     813
     814/** Constructor for class HessianMatrix.
     815 */
     816HessianMatrix::HessianMatrix() : MatrixContainer()
     817{
     818   IsSymmetric = true;
     819}
     820
     821/** Sums the hessian entries with each factor and put into last element of \a ***Matrix.
     822 * Sums over "E"-terms to create the "F"-terms
     823 * \param Matrix MatrixContainer with matrices (LevelCounter by *ColumnCounter) with all the energies.
     824 * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order
     825 * \param Order bond order
     826 * \return true if summing was successful
     827 */
     828bool HessianMatrix::SumSubManyBodyTerms(class MatrixContainer &MatrixValues, class KeySetsContainer &KeySet, int Order)
     829{
     830  // go through each order
     831  for (int CurrentFragment=0;CurrentFragment<KeySet.FragmentsPerOrder[Order];CurrentFragment++) {
     832    //cout << "Current Fragment is " << CurrentFragment << "/" << KeySet.OrderSet[Order][CurrentFragment] << "." << endl;
     833    // then go per order through each suborder and pick together all the terms that contain this fragment
     834    for(int SubOrder=0;SubOrder<=Order;SubOrder++) { // go through all suborders up to the desired order
     835      for (int j=0;j<KeySet.FragmentsPerOrder[SubOrder];j++) { // go through all possible fragments of size suborder
     836        if (KeySet.Contains(KeySet.OrderSet[Order][CurrentFragment], KeySet.OrderSet[SubOrder][j])) {
     837          //cout << "Current other fragment is " << j << "/" << KeySet.OrderSet[SubOrder][j] << "." << endl;
     838          // if the fragment's indices are all in the current fragment
     839          for(int k=0;k<RowCounter[ KeySet.OrderSet[SubOrder][j] ];k++) { // go through all atoms in this fragment
     840            int m = MatrixValues.Indices[ KeySet.OrderSet[SubOrder][j] ][k];
     841            //cout << "Current row index is " << k << "/" << m << "." << endl;
     842            if (m != -1) { // if it's not an added hydrogen
     843              for (int l=0;l<RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ];l++) { // look for the corresponding index in the current fragment
     844                //cout << "Comparing " << m << " with " << MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][l] << "." << endl;
     845                if (m == MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][l]) {
     846                  m = l;
     847                  break; 
     848                }
     849              }
     850              //cout << "Corresponding row index for " << k << " in CurrentFragment is " << m << "." << endl;
     851              if (m > RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ]) {
     852                cerr << "In fragment No. " << KeySet.OrderSet[Order][CurrentFragment]   << " current row index " << m << " is greater than " << RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ] << "!" << endl;
     853                return false;
     854              }
     855             
     856              for(int l=0;l<ColumnCounter[ KeySet.OrderSet[SubOrder][j] ];l++) {
     857                int n = MatrixValues.Indices[ KeySet.OrderSet[SubOrder][j] ][l];
     858                //cout << "Current column index is " << l << "/" << n << "." << endl;
     859                if (n != -1) { // if it's not an added hydrogen
     860                  for (int p=0;p<ColumnCounter[ KeySet.OrderSet[Order][CurrentFragment] ];p++) { // look for the corresponding index in the current fragment
     861                    //cout << "Comparing " << n << " with " << MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][p] << "." << endl;
     862                    if (n == MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][p]) {
     863                      n = p;
     864                      break; 
     865                    }
     866                  }
     867                  //cout << "Corresponding column index for " << l << " in CurrentFragment is " << n << "." << endl;
     868                  if (n > ColumnCounter[ KeySet.OrderSet[Order][CurrentFragment] ]) {
     869                    cerr << "In fragment No. " << KeySet.OrderSet[Order][CurrentFragment]   << " current column index " << n << " is greater than " << ColumnCounter[ KeySet.OrderSet[Order][CurrentFragment] ] << "!" << endl;
     870                    return false;
     871                  }
     872                  if (Order == SubOrder) { // equal order is always copy from Energies
     873                    //cout << "Adding " << MatrixValues.Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l] << " from [" << k << "][" << l << "] onto [" << m << "][" << n << "]." << endl;
     874                    Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][n] += MatrixValues.Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l];
     875                  } else {
     876                    //cout << "Subtracting " << Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l] << " from [" << k << "][" << l << "] onto [" << m << "][" << n << "]." << endl;
     877                    Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][n] -= Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l];
     878                  }
     879                }
     880              }
     881            }
     882            //if ((ColumnCounter[ KeySet.OrderSet[SubOrder][j] ]>1) && (RowCounter[0]-1 >= 1))
     883             //cout << "Fragments[ KeySet.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySet.OrderSet[Order][CurrentFragment] << " ][" << RowCounter[0]-1 << "][" << 1 << "] = " <<  Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][RowCounter[0]-1][1] << endl;
     884          }
     885        } else {
     886          //cout << "Fragment " << KeySet.OrderSet[SubOrder][j] << " is not contained in fragment " << KeySet.OrderSet[Order][CurrentFragment] << "." << endl;
     887        }
     888      }
     889    }
     890   //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;
     891  }
     892 
     893  return true;
     894};
     895
     896/** Calls MatrixContainer::ParseFragmentMatrix() and additionally allocates last plus one matrix.
     897 * \param *name directory with files
     898 * \param *prefix prefix of each matrix file
     899 * \param *suffix suffix of each matrix file
     900 * \param skiplines number of inital lines to skip
     901 * \param skiplines number of inital columns to skip
     902 * \return parsing successful
     903 */
     904bool HessianMatrix::ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns)
     905{
     906  char filename[1023];
     907  ifstream input;
     908  stringstream file;
     909  int nr;
     910  bool status = MatrixContainer::ParseFragmentMatrix(name, prefix, suffix, skiplines, skipcolumns);
     911
     912  if (status) {
     913    // count number of atoms for last plus one matrix
     914    file << name << FRAGMENTPREFIX << KEYSETFILE;
     915    input.open(file.str().c_str(), ios::in);
     916    if (input == NULL) {
     917      cout << endl << "Unable to open " << file.str() << ", is the directory correct?" << endl;
     918      return false;
     919    }
     920    RowCounter[MatrixCounter] = 0;
     921    ColumnCounter[MatrixCounter] = 0;
     922    while (!input.eof()) {
     923      input.getline(filename, 1023);
     924      stringstream zeile(filename);
     925      while (!zeile.eof()) {
     926        zeile >> nr;
     927        //cout << "Current index: " << nr << "." << endl;
     928        if (nr > RowCounter[MatrixCounter]) {
     929          RowCounter[MatrixCounter] = nr;
     930          ColumnCounter[MatrixCounter] = nr;
     931        }
     932      }
     933    }
     934    RowCounter[MatrixCounter]++;    // nr start at 0, count starts at 1
     935    ColumnCounter[MatrixCounter]++;    // nr start at 0, count starts at 1
     936    input.close();
     937 
     938    // allocate last plus one matrix
     939    cout << "Allocating last plus one matrix with " << (RowCounter[MatrixCounter]+1) << " rows and " << ColumnCounter[MatrixCounter] << " columns." << endl;
     940    Matrix[MatrixCounter] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixCounter]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]");
     941    for(int j=0;j<=RowCounter[MatrixCounter];j++)
     942      Matrix[MatrixCounter][j] = (double *) Malloc(sizeof(double)*ColumnCounter[MatrixCounter], "MatrixContainer::ParseFragmentMatrix: *Matrix[][]");
     943
     944    // try independently to parse global forcesuffix file if present
     945    strncpy(filename, name, 1023);
     946    strncat(filename, prefix, 1023-strlen(filename));
     947    strncat(filename, suffix.c_str(), 1023-strlen(filename));
     948    ParseMatrix(filename, skiplines, skipcolumns, MatrixCounter);
     949  }
     950
     951
     952  return status;
    673953};
    674954
     
    678958 */
    679959KeySetsContainer::KeySetsContainer() {
    680         KeySets = NULL;
    681         AtomCounter = NULL;
    682         FragmentCounter = 0;
    683         Order = 0;
    684         FragmentsPerOrder = 0;
    685         OrderSet = NULL;
     960  KeySets = NULL;
     961  AtomCounter = NULL;
     962  FragmentCounter = 0;
     963  Order = 0;
     964  FragmentsPerOrder = 0;
     965  OrderSet = NULL;
    686966};
    687967
     
    689969 */
    690970KeySetsContainer::~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");
     971  for(int i=FragmentCounter;i--;)
     972    Free((void **)&KeySets[i], "KeySetsContainer::~KeySetsContainer: *KeySets[]");
     973  for(int i=Order;i--;)
     974    Free((void **)&OrderSet[i], "KeySetsContainer::~KeySetsContainer: *OrderSet[]");
     975  Free((void **)&KeySets, "KeySetsContainer::~KeySetsContainer: **KeySets");
     976  Free((void **)&OrderSet, "KeySetsContainer::~KeySetsContainer: **OrderSet");
     977  Free((void **)&AtomCounter, "KeySetsContainer::~KeySetsContainer: *AtomCounter");
     978  Free((void **)&FragmentsPerOrder, "KeySetsContainer::~KeySetsContainer: *FragmentsPerOrder");
    699979};
    700980
     
    706986 */
    707987bool 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;
     988  ifstream input;
     989  char *FragmentNumber = NULL;
     990  stringstream file;
     991  char filename[1023];
     992
     993  FragmentCounter = FCounter;
     994  cout << "Parsing key sets." << endl;
     995  KeySets = (int **) Malloc(sizeof(int *)*FragmentCounter, "KeySetsContainer::ParseKeySets: **KeySets");
     996  for(int i=FragmentCounter;i--;)
     997    KeySets[i] = NULL;
     998  file << name << FRAGMENTPREFIX << KEYSETFILE;
     999  input.open(file.str().c_str(), ios::in);
     1000  if (input == NULL) {
     1001    cout << endl << "Unable to open " << file.str() << ", is the directory correct?" << endl;
     1002    return false;
     1003  }
     1004
     1005  AtomCounter = (int *) Malloc(sizeof(int)*FragmentCounter, "KeySetsContainer::ParseKeySets: *RowCounter");
     1006  for(int i=0;(i<FragmentCounter) && (!input.eof());i++) {
     1007    stringstream line;
     1008    AtomCounter[i] = ACounter[i];
     1009    // parse the values
     1010    KeySets[i] = (int *) Malloc(sizeof(int)*AtomCounter[i], "KeySetsContainer::ParseKeySets: *KeySets[]");
     1011    for(int j=AtomCounter[i];j--;)
     1012      KeySets[i][j] = -1;
     1013    FragmentNumber = FixedDigitNumber(FragmentCounter, i);
     1014    //cout << FRAGMENTPREFIX << FragmentNumber << "[" << AtomCounter[i] << "]:";
     1015    Free((void **)&FragmentNumber, "KeySetsContainer::ParseKeySets: *FragmentNumber");
     1016    input.getline(filename, 1023);
     1017    line.str(filename);
     1018    for(int j=0;(j<AtomCounter[i]) && (!line.eof());j++) {
     1019      line >> KeySets[i][j];
     1020      //cout << " " << KeySets[i][j];
     1021    }
     1022    //cout << endl;
     1023  }
     1024  input.close();
     1025  return true;
    7461026};
    7471027
     
    7511031bool KeySetsContainer::ParseManyBodyTerms()
    7521032{
    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;
     1033  int Counter;
     1034
     1035  cout << "Creating Fragment terms." << endl;
     1036  // scan through all to determine maximum order
     1037  Order=0;
     1038  for(int i=FragmentCounter;i--;) {
     1039    Counter=0;
     1040    for(int j=AtomCounter[i];j--;)
     1041      if (KeySets[i][j] != -1)
     1042        Counter++;
     1043    if (Counter > Order)
     1044      Order = Counter;
     1045  }
     1046  cout << "Found Order is " << Order << "." << endl;
     1047
     1048  // scan through all to determine fragments per order
     1049  FragmentsPerOrder = (int *) Malloc(sizeof(int)*Order, "KeySetsContainer::ParseManyBodyTerms: *FragmentsPerOrder");
     1050  for(int i=Order;i--;)
     1051    FragmentsPerOrder[i] = 0;
     1052  for(int i=FragmentCounter;i--;) {
     1053    Counter=0;
     1054    for(int j=AtomCounter[i];j--;)
     1055      if (KeySets[i][j] != -1)
     1056        Counter++;
     1057    FragmentsPerOrder[Counter-1]++;
     1058  }
     1059  for(int i=0;i<Order;i++)
     1060    cout << "Found No. of Fragments of Order " << i+1 << " is " << FragmentsPerOrder[i] << "." << endl;
     1061
     1062  // scan through all to gather indices to each order set
     1063  OrderSet = (int **) Malloc(sizeof(int *)*Order, "KeySetsContainer::ParseManyBodyTerms: **OrderSet");
     1064  for(int i=Order;i--;)
     1065    OrderSet[i] = (int *) Malloc(sizeof(int)*FragmentsPerOrder[i], "KeySetsContainer::ParseManyBodyTermsKeySetsContainer::ParseManyBodyTerms: *OrderSet[]");
     1066  for(int i=Order;i--;)
     1067    FragmentsPerOrder[i] = 0;
     1068  for(int i=FragmentCounter;i--;) {
     1069    Counter=0;
     1070    for(int j=AtomCounter[i];j--;)
     1071      if (KeySets[i][j] != -1)
     1072        Counter++;
     1073    OrderSet[Counter-1][FragmentsPerOrder[Counter-1]] = i;
     1074    FragmentsPerOrder[Counter-1]++;
     1075  }
     1076  cout << "Printing OrderSet." << endl;
     1077  for(int i=0;i<Order;i++) {
     1078    for (int j=0;j<FragmentsPerOrder[i];j++) {
     1079      cout << " " << OrderSet[i][j];
     1080    }
     1081    cout << endl;
     1082  }
     1083  cout << endl;
     1084
     1085
     1086  return true;
    8071087};
    8081088
     
    8141094bool KeySetsContainer::Contains(const int GreaterSet, const int SmallerSet)
    8151095{
    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;
     1096  bool result = true;
     1097  bool intermediate;
     1098  if ((GreaterSet < 0) || (SmallerSet < 0) || (GreaterSet > FragmentCounter) || (SmallerSet > FragmentCounter)) // index out of bounds
     1099    return false;
     1100  for(int i=AtomCounter[SmallerSet];i--;) {
     1101    intermediate = false;
     1102    for (int j=AtomCounter[GreaterSet];j--;)
     1103      intermediate = (intermediate || ((KeySets[SmallerSet][i] == KeySets[GreaterSet][j]) || (KeySets[SmallerSet][i] == -1)));
     1104    result = result && intermediate;
     1105  }
     1106
     1107  return result;
    8281108};
    8291109
  • src/parser.hpp

    r375b458 r51c910  
    1919
    2020#define EnergySuffix ".energy.all"
     21#define EnergyFragmentSuffix ".energyfragment.all"
     22#define ForcesSuffix ".forces.all"
     23#define ForceFragmentSuffix ".forcefragment.all"
    2124#define HcorrectionSuffix ".Hcorrection.all"
    22 #define ForcesSuffix ".forces.all"
     25#define HcorrectionFragmentSuffix ".Hcorrectionfragment.all"
     26#define HessianSuffix ".hessian_xx.all"
     27#define HessianFragmentSuffix ".hessianfragment_xx.all"
     28#define OrderSuffix ".Order"
    2329#define ShieldingSuffix ".sigma_all.csv"
    2430#define ShieldingPASSuffix ".sigma_all_PAS.csv"
    2531#define ShieldingFragmentSuffix ".sigma_all_fragment.all"
    2632#define ShieldingPASFragmentSuffix ".sigma_all_PAS_fragment.all"
     33#define ChiSuffix ".chi_all.csv"
     34#define ChiPASSuffix ".chi_all_PAS.csv"
     35#define ChiFragmentSuffix ".chi_all_fragment.all"
     36#define ChiPASFragmentSuffix ".chi_all_PAS_fragment.all"
    2737#define TimeSuffix ".speed"
    28 #define EnergyFragmentSuffix ".energyfragment.all"
    29 #define HcorrectionFragmentSuffix ".Hcorrectionfragment.all"
    30 #define ForceFragmentSuffix ".forcefragment.all"
    31 #define OrderSuffix ".Order"
    3238
    3339// ======================================= FUNCTIONS ==========================================
     
    4046
    4147class MatrixContainer {
    42         public:
    43                 double ***Matrix;
    44                 int **Indices;
    45                 char *Header;
    46                 int MatrixCounter;
    47                 int *RowCounter;
    48                 int ColumnCounter;
    49 
    50         MatrixContainer();
    51         virtual ~MatrixContainer();
    52 
    53         bool ParseMatrix(const char *name, int skiplines, int skipcolumns, int MatrixNr);
    54         virtual bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns);
    55         bool AllocateMatrix(char *GivenHeader, int MCounter, int *RCounter, int CCounter);
    56         bool ResetMatrix();
    57         double FindMinValue();
    58         double FindMaxValue();
    59         bool SetLastMatrix(double value, int skipcolumns);
    60         bool SetLastMatrix(double **values, int skipcolumns);
    61         //bool ParseIndices();
    62         //bool SumSubValues();
    63         bool SumSubManyBodyTerms(class MatrixContainer &Matrix, class KeySetsContainer &KeySet, int Order);
    64         bool WriteTotalFragments(const char *name, const char *prefix);
    65         bool WriteLastMatrix(const char *name, const char *prefix, const char *suffix);
     48  public:
     49    double ***Matrix;
     50    int **Indices;
     51    char **Header;
     52    int MatrixCounter;
     53    int *RowCounter;
     54    int *ColumnCounter;
     55 
     56  MatrixContainer();
     57  ~MatrixContainer();
     58 
     59  bool InitialiseIndices(class MatrixContainer *Matrix = NULL);
     60  bool ParseMatrix(const char *name, int skiplines, int skipcolumns, int MatrixNr);
     61  virtual bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns);
     62  bool AllocateMatrix(char **GivenHeader, int MCounter, int *RCounter, int *CCounter);
     63  bool ResetMatrix();
     64  double FindMinValue();
     65  double FindMaxValue();
     66  bool SetLastMatrix(double value, int skipcolumns);
     67  bool SetLastMatrix(double **values, int skipcolumns);
     68  //bool ParseIndices();
     69  //bool SumSubValues();
     70  bool SumSubManyBodyTerms(class MatrixContainer &Matrix, class KeySetsContainer &KeySet, int Order);
     71  bool WriteTotalFragments(const char *name, const char *prefix);
     72  bool WriteLastMatrix(const char *name, const char *prefix, const char *suffix);
    6673};
    6774
     
    6976
    7077class 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);
     78  public:
     79    bool ParseIndices();
     80    bool SumSubEnergy(class EnergyMatrix &Fragments, class EnergyMatrix *CorrectionFragments, class KeySetsContainer &KeySet, int Order, double sign);
     81    bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns);
    7582};
    7683
     
    7885
    7986class 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);
     87  public:
     88    bool ParseIndices(char *name);
     89    bool SumSubForces(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign);
     90    bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns);
     91};
     92
     93// ======================================= CLASS HessianMatrix =============================
     94
     95class HessianMatrix : public MatrixContainer {
     96  public:
     97    HessianMatrix();
     98    //~HessianMatrix();
     99    bool ParseIndices(char *name);
     100    bool SumSubManyBodyTerms(class MatrixContainer &MatrixValues, class KeySetsContainer &KeySet, int Order);
     101    bool SumSubHessians(class HessianMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign);
     102    bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns);
     103  private:
     104    bool IsSymmetric;
    84105};
    85106
     
    87108
    88109class KeySetsContainer {
    89         public:
    90                 int **KeySets;
    91                 int *AtomCounter;
    92                 int FragmentCounter;
    93                 int Order;
    94                 int *FragmentsPerOrder;
    95                 int **OrderSet;
     110  public:
     111    int **KeySets;
     112    int *AtomCounter;
     113    int FragmentCounter;
     114    int Order;
     115    int *FragmentsPerOrder;
     116    int **OrderSet;
    96117
    97         KeySetsContainer();
    98         ~KeySetsContainer();
     118  KeySetsContainer();
     119  ~KeySetsContainer();
    99120
    100         bool ParseKeySets(const char *name, const int *ACounter, const int FCounter);
    101         bool ParseManyBodyTerms();
    102         bool Contains(const int GreaterSet, const int SmallerSet);
     121  bool ParseKeySets(const char *name, const int *ACounter, const int FCounter);
     122  bool ParseManyBodyTerms();
     123  bool Contains(const int GreaterSet, const int SmallerSet);
    103124};
    104125
  • src/periodentafel.cpp

    r375b458 r51c910  
    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};
  • src/verbose.cpp

    r375b458 r51c910  
    2222ostream& operator<<(ostream& ost,const Verbose& m)
    2323{
    24         return m.print(ost);
     24  return m.print(ost);
    2525};
    2626
     
    3333ostream& Binary::print (ostream &ost) const
    3434{
    35         int bits = 1, counter = 1;
    36         while ((bits = 1 << counter) < BinaryNumber)
    37                 counter++;
    38         for (int i=0;i<counter-1;i++) {
    39                 if ((BinaryNumber & (1 << i)) == 0)
    40                         ost.put('0');
    41                 else
    42                         ost.put('1');
    43         }
    44         ost.put('b');
    45         //cout << "Binary(.) called." << endl;
    46         return ost;
     35  int bits = 1, counter = 1;
     36  while ((bits = 1 << counter) < BinaryNumber)
     37    counter++;
     38  for (int i=0;i<counter-1;i++) {
     39    if ((BinaryNumber & (1 << i)) == 0)
     40      ost.put('0');
     41     else
     42      ost.put('1');
     43  }
     44  ost.put('b');
     45  //cout << "Binary(.) called." << endl;
     46  return ost;
    4747};
    4848
     
    5656ostream& operator<<(ostream& ost,const Binary& m)
    5757{
    58         return m.print(ost);
     58  return m.print(ost);
    5959};
Note: See TracChangeset for help on using the changeset viewer.