Changes in / [375b458:51c910]
- Location:
- src
- Files:
-
- 1 added
- 22 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Makefile.am
r375b458 r51c910 10 10 11 11 12 #EXTRA_DIST = ${molecuilder_DATA}12 EXTRA_DIST = ${molecuilder_DATA} -
src/analyzer.cpp
r375b458 r51c910 23 23 int main(int argc, char **argv) 24 24 { 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; 427 560 }; 428 561 -
src/atom.cpp
r375b458 r51c910 13 13 atom::atom() 14 14 { 15 16 17 18 father = this;// generally, father is itself19 20 21 22 23 24 25 26 27 28 29 30 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; 31 31 }; 32 32 … … 35 35 atom::~atom() 36 36 { 37 38 37 Free((void **)&Name, "atom::~atom: *Name"); 38 Free((void **)&ComponentNr, "atom::~atom: *ComponentNr"); 39 39 }; 40 40 … … 45 45 atom *atom::GetTrueFather() 46 46 { 47 48 49 50 51 52 53 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; 54 54 }; 55 55 … … 62 62 bool atom::Output(int ElementNo, int AtomNo, ofstream *out, const char *comment) const 63 63 { 64 65 *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t"<< fixed << setprecision(9) << showpoint;66 67 68 69 70 71 72 73 74 75 76 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; 77 77 }; 78 78 … … 82 82 bool atom::OutputXYZLine(ofstream *out) const 83 83 { 84 85 86 87 88 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; 89 89 }; 90 90 91 ostream & operator << (ostream &ost, atom &a)91 ostream & operator << (ostream &ost, const atom &a) 92 92 { 93 94 93 ost << "[" << a.Name << "|" << &a << "]"; 94 return ost; 95 95 }; 96 96 … … 101 101 bool atom::Compare(atom &ptr) 102 102 { 103 104 105 106 103 if (nr < ptr.nr) 104 return true; 105 else 106 return false; 107 107 }; 108 108 109 109 bool operator < (atom &a, atom &b) 110 110 { 111 111 return a.Compare(b); 112 112 }; 113 113 -
src/bond.cpp
r375b458 r51c910 14 14 bond::bond() 15 15 { 16 17 18 19 20 21 22 23 24 25 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; 26 26 }; 27 27 … … 34 34 bond::bond(atom *left, atom *right, int degree=1, int number=0) 35 35 { 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 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; 51 51 }; 52 52 bond::bond(atom *left, atom *right) 53 53 { 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 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; 69 69 }; 70 70 … … 73 73 bond::~bond() 74 74 { 75 76 77 78 79 80 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 } 82 82 }; 83 83 84 ostream & operator << (ostream &ost, bond &b)84 ostream & operator << (ostream &ost, const bond &b) 85 85 { 86 87 86 ost << "[" << b.leftatom->Name << " <" << b.BondDegree << "(H" << b.HydrogenBond << ")>" << b.rightatom->Name << "]"; 87 return ost; 88 88 }; 89 89 … … 94 94 atom * bond::GetOtherAtom(atom *Atom) const 95 95 { 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; 101 102 }; 102 103 … … 107 108 bond * bond::GetFirstBond() 108 109 { 109 110 return GetFirst(this); 110 111 }; 111 112 … … 116 117 bond * bond::GetLastBond() 117 118 { 118 119 return GetLast(this); 119 120 }; 120 121 … … 124 125 enum Shading bond::IsUsed() 125 126 { 126 127 return Used; 127 128 }; 128 129 … … 133 134 bool bond::Contains(const atom *ptr) 134 135 { 135 136 return ((leftatom == ptr) || (rightatom == ptr)); 136 137 }; 137 138 … … 142 143 bool bond::Contains(const int number) 143 144 { 144 145 return ((leftatom->nr == number) || (rightatom->nr == number)); 145 146 }; 146 147 … … 149 150 */ 150 151 bool bond::MarkUsed(enum Shading color) { 151 152 153 154 155 156 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 } 158 159 }; 159 160 … … 162 163 */ 163 164 void bond::ResetUsed() { 164 165 Used = white; 165 166 }; -
src/boundary.cpp
r375b458 r51c910 15 15 BoundaryPointSet::BoundaryPointSet() 16 16 { 17 18 17 LinesCount = 0; 18 Nr = -1; 19 19 } 20 20 ; … … 22 22 BoundaryPointSet::BoundaryPointSet(atom *Walker) 23 23 { 24 25 26 24 node = Walker; 25 LinesCount = 0; 26 Nr = Walker->nr; 27 27 } 28 28 ; … … 30 30 BoundaryPointSet::~BoundaryPointSet() 31 31 { 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(); 36 37 } 37 38 ; … … 39 40 void BoundaryPointSet::AddLine(class BoundaryLineSet *line) 40 41 { 41 42 43 44 45 46 47 48 49 50 51 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++; 52 53 } 53 54 ; … … 56 57 operator <<(ostream &ost, BoundaryPointSet &a) 57 58 { 58 59 59 ost << "[" << a.Nr << "|" << a.node->Name << "]"; 60 return ost; 60 61 } 61 62 ; … … 65 66 BoundaryLineSet::BoundaryLineSet() 66 67 { 67 68 69 70 68 for (int i = 0; i < 2; i++) 69 endpoints[i] = NULL; 70 TrianglesCount = 0; 71 Nr = -1; 71 72 } 72 73 ; … … 74 75 BoundaryLineSet::BoundaryLineSet(class BoundaryPointSet *Point[2], int number) 75 76 { 76 77 78 79 80 81 82 83 84 85 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; 86 87 } 87 88 ; … … 89 90 BoundaryLineSet::~BoundaryLineSet() 90 91 { 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; 109 109 } 110 110 ; … … 113 113 BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle) 114 114 { 115 116 117 118 115 cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "." 116 << endl; 117 triangles.insert(TrianglePair(triangle->Nr, triangle)); 118 TrianglesCount++; 119 119 } 120 120 ; … … 123 123 operator <<(ostream &ost, BoundaryLineSet &a) 124 124 { 125 126 127 125 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," 126 << a.endpoints[1]->node->Name << "]"; 127 return ost; 128 128 } 129 129 ; … … 134 134 BoundaryTriangleSet::BoundaryTriangleSet() 135 135 { 136 137 138 139 140 141 136 for (int i = 0; i < 3; i++) 137 { 138 endpoints[i] = NULL; 139 lines[i] = NULL; 140 } 141 Nr = -1; 142 142 } 143 143 ; 144 144 145 145 BoundaryTriangleSet::BoundaryTriangleSet(class BoundaryLineSet *line[3], 146 147 { 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 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; 184 184 } 185 185 ; … … 187 187 BoundaryTriangleSet::~BoundaryTriangleSet() 188 188 { 189 190 191 192 193 194 195 196 197 198 199 200 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 } 202 202 } 203 203 ; … … 206 206 BoundaryTriangleSet::GetNormalVector(Vector &OtherVector) 207 207 { 208 209 210 211 212 213 214 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.); 215 215 } 216 216 ; … … 219 219 operator <<(ostream &ost, BoundaryTriangleSet &a) 220 220 { 221 222 223 221 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," 222 << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]"; 223 return ost; 224 224 } 225 225 ; … … 235 235 GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2) 236 236 { 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 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; 259 259 } 260 260 ; … … 270 270 GetBoundaryPoints(ofstream *out, molecule *mol) 271 271 { 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 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 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 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 //else375 //*out << i << ": " << *runner->second.second;376 //i++;377 //}378 //*out << endl;379 //}380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 //*out << "SideA: ";417 //SideA.Output(out);418 //*out << endl;419 420 421 422 //*out << "SideB: ";423 //SideB.Output(out);424 //*out << endl;425 426 427 428 429 //*out << "SideC: ";430 //SideC.Output(out);431 //*out << endl;432 433 434 435 //*out << "SideH: ";436 //SideH.Output(out);437 //*out << endl;438 439 440 441 442 443 444 445 446 447 448 449 450 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 453 454 455 456 457 458 459 460 461 462 463 464 465 466 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; 467 467 } 468 468 ; … … 478 478 double * 479 479 GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, 480 481 { 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 480 bool IsAngstroem) 481 { 482 // get points on boundary of NULL was given as parameter 483 bool BoundaryFreeFlag = false; 484 Boundaries *BoundaryPoints = BoundaryPtr; 485 if (BoundaryPoints == NULL) 486 { 487 BoundaryFreeFlag = true; 488 BoundaryPoints = GetBoundaryPoints(out, mol); 489 } 490 else 491 { 492 *out << Verbose(1) << "Using given boundary points set." << endl; 493 } 494 // determine biggest "diameter" of cluster for each axis 495 Boundaries::iterator Neighbour, OtherNeighbour; 496 double *GreatestDiameter = new double[NDIM]; 497 for (int i = 0; i < NDIM; i++) 498 GreatestDiameter[i] = 0.; 499 double OldComponent, tmp, w1, w2; 500 Vector DistanceVector, OtherVector; 501 int component, Othercomponent; 502 for (int axis = 0; axis < NDIM; axis++) 503 { // regard each projected plane 504 //*out << Verbose(1) << "Current axis is " << axis << "." << endl; 505 for (int j = 0; j < 2; j++) 506 { // and for both axis on the current plane 507 component = (axis + j + 1) % NDIM; 508 Othercomponent = (axis + 1 + ((j + 1) & 1)) % NDIM; 509 //*out << Verbose(1) << "Current component is " << component << ", Othercomponent is " << Othercomponent << "." << endl; 510 for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner 511 != BoundaryPoints[axis].end(); runner++) 512 { 513 //*out << Verbose(2) << "Current runner is " << *(runner->second.second) << "." << endl; 514 // seek for the neighbours pair where the Othercomponent sign flips 515 Neighbour = runner; 516 Neighbour++; 517 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around 518 Neighbour = BoundaryPoints[axis].begin(); 519 DistanceVector.CopyVector(&runner->second.second->x); 520 DistanceVector.SubtractVector(&Neighbour->second.second->x); 521 do 522 { // seek for neighbour pair where it flips 523 OldComponent = DistanceVector.x[Othercomponent]; 524 Neighbour++; 525 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around 526 Neighbour = BoundaryPoints[axis].begin(); 527 DistanceVector.CopyVector(&runner->second.second->x); 528 DistanceVector.SubtractVector(&Neighbour->second.second->x); 529 //*out << Verbose(3) << "OldComponent is " << OldComponent << ", new one is " << DistanceVector.x[Othercomponent] << "." << endl; 530 } 531 while ((runner != Neighbour) && (fabs(OldComponent / fabs( 532 OldComponent) - DistanceVector.x[Othercomponent] / fabs( 533 DistanceVector.x[Othercomponent])) < MYEPSILON)); // as long as sign does not flip 534 if (runner != Neighbour) 535 { 536 OtherNeighbour = Neighbour; 537 if (OtherNeighbour == BoundaryPoints[axis].begin()) // make it wrap around 538 OtherNeighbour = BoundaryPoints[axis].end(); 539 OtherNeighbour--; 540 //*out << Verbose(2) << "The pair, where the sign of OtherComponent flips, is: " << *(Neighbour->second.second) << " and " << *(OtherNeighbour->second.second) << "." << endl; 541 // now we have found the pair: Neighbour and OtherNeighbour 542 OtherVector.CopyVector(&runner->second.second->x); 543 OtherVector.SubtractVector(&OtherNeighbour->second.second->x); 544 //*out << Verbose(2) << "Distances to Neighbour and OtherNeighbour are " << DistanceVector.x[component] << " and " << OtherVector.x[component] << "." << endl; 545 //*out << Verbose(2) << "OtherComponents to Neighbour and OtherNeighbour are " << DistanceVector.x[Othercomponent] << " and " << OtherVector.x[Othercomponent] << "." << endl; 546 // do linear interpolation between points (is exact) to extract exact intersection between Neighbour and OtherNeighbour 547 w1 = fabs(OtherVector.x[Othercomponent]); 548 w2 = fabs(DistanceVector.x[Othercomponent]); 549 tmp = fabs((w1 * DistanceVector.x[component] + w2 550 * OtherVector.x[component]) / (w1 + w2)); 551 // mark if it has greater diameter 552 //*out << Verbose(2) << "Comparing current greatest " << GreatestDiameter[component] << " to new " << tmp << "." << endl; 553 GreatestDiameter[component] = (GreatestDiameter[component] 554 > tmp) ? GreatestDiameter[component] : tmp; 555 } //else 556 //*out << Verbose(2) << "Saw no sign flip, probably top or bottom node." << endl; 557 } 558 } 559 } 560 *out << Verbose(0) << "RESULT: The biggest diameters are " 561 << GreatestDiameter[0] << " and " << GreatestDiameter[1] << " and " 562 << GreatestDiameter[2] << " " << (IsAngstroem ? "angstrom" 563 : "atomiclength") << "." << endl; 564 565 // free reference lists 566 if (BoundaryFreeFlag) 567 delete[] (BoundaryPoints); 568 569 return GreatestDiameter; 570 570 } 571 571 ; … … 579 579 void write_vrml_file(ofstream *out, ofstream *vrmlfile, class Tesselation *Tess, class molecule *mol) 580 580 { 581 582 583 584 585 586 587 588 589 590 591 592 *vrmlfile << "Sphere {" << endl << ""; // 2 is sphere type593 594 595 596 597 598 599 600 601 *vrmlfile << "3" << endl << ""; // 2 is round-ended cylinder type602 603 604 605 606 607 608 609 610 611 612 *vrmlfile << "1" << endl << ""; // 1 is triangle type613 614 for (int j=0;j<NDIM;j++)// and for each node all NDIM coordinates615 616 617 618 *vrmlfile << "1. 0. 0." << endl;// red as colour619 *vrmlfile << "18" << endl << "0.5 0.5 0.5" << endl; // 18 is transparency type for previous object620 621 622 623 624 581 atom *Walker = mol->start; 582 bond *Binder = mol->first; 583 int i; 584 Vector *center = mol->DetermineCenterOfAll(out); 585 if (vrmlfile != NULL) { 586 //cout << Verbose(1) << "Writing Raster3D file ... "; 587 *vrmlfile << "#VRML V2.0 utf8" << endl; 588 *vrmlfile << "#Created by molecuilder" << endl; 589 *vrmlfile << "#All atoms as spheres" << endl; 590 while (Walker->next != mol->end) { 591 Walker = Walker->next; 592 *vrmlfile << "Sphere {" << endl << " "; // 2 is sphere type 593 for (i=0;i<NDIM;i++) 594 *vrmlfile << Walker->x.x[i]+center->x[i] << " "; 595 *vrmlfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour 596 } 597 598 *vrmlfile << "# All bonds as vertices" << endl; 599 while (Binder->next != mol->last) { 600 Binder = Binder->next; 601 *vrmlfile << "3" << endl << " "; // 2 is round-ended cylinder type 602 for (i=0;i<NDIM;i++) 603 *vrmlfile << Binder->leftatom->x.x[i]+center->x[i] << " "; 604 *vrmlfile << "\t0.03\t"; 605 for (i=0;i<NDIM;i++) 606 *vrmlfile << Binder->rightatom->x.x[i]+center->x[i] << " "; 607 *vrmlfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour 608 } 609 610 *vrmlfile << "# All tesselation triangles" << endl; 611 for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) { 612 *vrmlfile << "1" << endl << " "; // 1 is triangle type 613 for (i=0;i<3;i++) { // print each node 614 for (int j=0;j<NDIM;j++) // and for each node all NDIM coordinates 615 *vrmlfile << TriangleRunner->second->endpoints[i]->node->x.x[j]+center->x[j] << " "; 616 *vrmlfile << "\t"; 617 } 618 *vrmlfile << "1. 0. 0." << endl; // red as colour 619 *vrmlfile << "18" << endl << " 0.5 0.5 0.5" << endl; // 18 is transparency type for previous object 620 } 621 } else { 622 cerr << "ERROR: Given vrmlfile is " << vrmlfile << "." << endl; 623 } 624 delete(center); 625 625 }; 626 626 … … 633 633 void write_raster3d_file(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, class molecule *mol) 634 634 { 635 636 637 638 639 640 641 642 643 644 645 646 *rasterfile << "2" << endl << " ";// 2 is sphere type647 648 649 650 651 652 653 654 655 *rasterfile << "3" << endl << " ";// 2 is round-ended cylinder type656 657 658 659 660 661 662 663 664 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.00 0\n";666 667 *rasterfile << "1" << endl << " ";// 1 is triangle type668 for (i=0;i<3;i++) {// print each node669 for (int j=0;j<NDIM;j++)// and for each node all NDIM coordinates670 671 672 673 *rasterfile << "1. 0. 0." << endl;// red as colour674 //*rasterfile << "18" << endl << " 0.5 0.5 0.5" << endl;// 18 is transparency type for previous object675 676 *rasterfile << "9\nterminating special property\n";677 678 679 680 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); 681 681 }; 682 682 … … 688 688 void 689 689 write_tecplot_file(ofstream *out, ofstream *tecplot, 690 691 { 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 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 } 732 732 } 733 733 … … 743 743 double 744 744 VolumeOfConvexEnvelope(ofstream *out, const char *filename, config *configuration, 745 746 { 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 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 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 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; 872 872 } 873 873 ; … … 883 883 void 884 884 PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol, 885 886 { 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 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; 993 993 } 994 994 ; … … 1000 1000 Tesselation::Tesselation() 1001 1001 { 1002 1003 1004 1005 1002 PointsOnBoundaryCount = 0; 1003 LinesOnBoundaryCount = 0; 1004 TrianglesOnBoundaryCount = 0; 1005 TriangleFilesWritten = 0; 1006 1006 } 1007 1007 ; … … 1012 1012 Tesselation::~Tesselation() 1013 1013 { 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 } 1022 1036 } 1023 1037 ; … … 1031 1045 Tesselation::GuessStartingTriangle(ofstream *out) 1032 1046 { 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 //// listing distances1064 //*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 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 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 } 1185 1199 } 1186 1200 ; … … 1191 1205 * -# if the lines contains to only one triangle 1192 1206 * -# We search all points in the boundary 1193 * 1194 * 1195 * 1196 * 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) 1197 1211 * \param *out output stream for debugging 1198 1212 * \param *configuration for IsAngstroem … … 1201 1215 void 1202 1216 Tesselation::TesselateOnBoundary(ofstream *out, config *configuration, 1203 1204 { 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 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 //else1294 //*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 //else1298 //*out << Verbose(4) << *(baseline->second->endpoints[1]) << " has no line to " << *(target->second) << " as endpoint." << endl;1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 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); 1423 1437 1424 1438 } … … 1431 1445 Tesselation::AddPoint(atom *Walker) 1432 1446 { 1433 1434 1435 1436 1437 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++; 1438 1452 } 1439 1453 ; … … 1447 1461 Tesselation::AddTrianglePoint(atom* Candidate, int n) 1448 1462 { 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 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 } 1463 1477 } 1464 1478 ; … … 1473 1487 void 1474 1488 Tesselation::AddTriangleLine(class BoundaryPointSet *a, 1475 1476 { 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 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 } 1512 1526 } 1513 1527 ; … … 1520 1534 { 1521 1535 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 */ 1535 1548 } 1536 1549 ; … … 1538 1551 1539 1552 double det_get(gsl_matrix *A, int inPlace) { 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 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; 1565 1578 }; 1566 1579 1567 1580 void get_sphere(Vector *center, Vector &a, Vector &b, Vector &c, double RADIUS) 1568 1581 { 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 center->x[0] =0.5 * m12/ m11;1604 1605 center->x[2] =0.5 * m14/ m11;1606 1607 1608 1609 1610 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); 1611 1624 }; 1612 1625 … … 1630 1643 */ 1631 1644 void 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"; 1686 1698 }; 1687 1699 1688 1700 /** This recursive function finds a third point, to form a triangle with two given ones. 1689 1701 * Two atoms are fixed, a candidate is supplied, additionally two vectors for direction distinction, a Storage area to \ 1690 * 1691 * 1692 * 1693 * 1694 * 1695 * 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. 1696 1708 * @param a first point 1697 1709 * @param b second point … … 1710 1722 */ 1711 1723 void 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"; 1864 1873 } 1865 1874 ; … … 1874 1883 void GetCenterofCircumcircle(Vector *Center, Vector *a, Vector *b, Vector *c) 1875 1884 { 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 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))); 1903 1912 }; 1904 1913 … … 1918 1927 double GetPathLengthonCircumCircle(Vector &CircleCenter, Vector &CirclePlaneNormal, double CircleRadius, Vector &NewSphereCenter, Vector &OldSphereCenter, Vector &NormalVector, Vector &SearchDirection) 1919 1928 { 1920 1921 1922 1923 1924 1925 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 1928 1929 1930 1931 1932 1933 1934 1935 if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)// acos is not unique on [0, 2.*M_PI), hence extra check to decide between two half intervals1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 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 } 1948 1957 }; 1949 1958 … … 1980 1989 // void Find_next_suitable_point(class BoundaryTriangleSet *BaseTriangle, class BoundaryLineSet *BaseLine, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC) 1981 1990 // { 1982 // 1983 // Vector CircleCenter;// center of the circle, i.e. of the band of sphere's centers1984 // 1985 // Vector OldSphereCenter;// center of the sphere defined by the three points of BaseTriangle1986 // Vector NewSphereCenter;// center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility1987 // Vector OtherNewSphereCenter;// center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility1988 // Vector NewNormalVector;// normal vector of the Candidate's triangle1989 // Vector SearchDirection;// vector that points out of BaseTriangle and is orthonormal to its NormalVector (i.e. the desired direction for the best Candidate)1990 // 1991 // 1992 // 1993 // 1994 // 1995 // 1996 // 1997 // 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; 1998 2007 // 1999 // 2008 // cout << Verbose(1) << "Begin of Find_next_suitable_point" << endl; 2000 2009 // 2001 // 2010 // cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << BaseTriangle->NormalVector << "." << endl; 2002 2011 // 2003 // 2004 // 2005 // 2006 // 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); 2007 2016 // 2008 // 2009 // 2010 // 2017 // // construct normal vector of circle 2018 // CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x); 2019 // CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x); 2011 2020 // 2012 // 2013 // 2014 // 2015 // 2016 // 2017 // 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; 2018 2027 // 2019 // 2020 // 2021 // helper.CopyVector(&BaseTriangle->NormalVector);// normal vector ensures that this is correct center of the two possible ones2022 // 2023 // 2024 // 2025 // 2026 // 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; 2027 2036 // 2028 // 2029 // 2030 // 2031 // 2032 // 2033 // 2034 // 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) { 2035 2044 // 2036 // 2037 // 2038 // 2039 // for(int i=0;i<3;i++)// just take next different endpoint2040 // 2041 // 2042 // 2043 // if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)// ohoh, SearchDirection points inwards!2044 // 2045 // 2046 // 2047 // 2048 // if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {// rotated the wrong way!2049 // 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 // } 2051 2060 // 2052 // if (LC->SetIndexToVector(&CircleCenter)) {// get cell for the starting atom2053 // 2054 // 2055 // 2056 // 2057 // 2058 // 2059 // 2060 // 2061 // 2062 // 2063 // 2064 // 2065 // 2066 // 2067 // 2068 // 2069 // 2070 // 2071 // 2072 // 2073 // 2074 // 2075 // 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); 2076 2085 // 2077 // 2078 // 2079 // 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; 2080 2089 // 2081 // 2082 // 2083 // 2090 // // construct both new centers 2091 // GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x)); 2092 // OtherNewSphereCenter.CopyVector(&NewSphereCenter); 2084 2093 // 2085 // 2086 // 2087 // 2088 // 2089 // 2090 // 2091 // 2092 // 2093 // 2094 // 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; 2095 2104 // 2096 // 2097 // 2098 // 2099 // 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; 2100 2109 // 2101 // 2102 // 2103 // 2104 // 2105 // 2106 // 2107 // 2108 // 2109 // 2110 // 2111 // 2112 // 2113 // 2114 // 2115 // 2116 // 2117 // 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 // } 2119 2128 // 2120 // 2121 // 2122 // 2123 // 2124 // 2125 // 2126 // 2127 // 2128 // 2129 // 2130 // 2131 // 2132 // 2133 // 2134 // 2135 // 2136 // 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 // } 2138 2147 // 2139 // 2148 // cout << Verbose(1) << "End of Find_next_suitable_point" << endl; 2140 2149 // }; 2141 2150 2142 2143 /** Checks whether the triangle consisting of the three atoms is already present.2144 * Searches for the points in Tesselation::PointsOnBoundary and checks their2145 * lines. If any of the three edges already has two triangles attached, false is2146 * returned.2147 * \param *out output stream for debugging2148 * \param *Candidates endpoints of the triangle candidate2149 * \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 endpoints2158 FindPoint = PointsOnBoundary.find(Candidates[i]->nr);2159 if (FindPoint != PointsOnBoundary.end())2160 TPS[i] = FindPoint->second;2161 else2162 TPS[i] = NULL;2163 }2164 2165 // check lines2166 for (int i=0;i<3;i++)2167 if (TPS[i] != NULL)2168 for (int j=i;j<3;j++)2169 if (TPS[j] != NULL) {2170 FindLine = TPS[i]->lines.find(TPS[j]->node->nr);2171 if ((FindLine != TPS[i]->lines.end()) && (FindLine->second->TrianglesCount > 1)) {2172 *out << "WARNING: Line " << *FindLine->second << " already present with " << FindLine->second->TrianglesCount << " triangles attached." << endl;2173 *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;2174 return false;2175 }2176 }2177 *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;2178 return true;2179 };2180 2151 2181 2152 /** This recursive function finds a third point, to form a triangle with two given ones. … … 2214 2185 void Find_third_point_for_Tesselation(Vector NormalVector, Vector SearchDirection, Vector OldSphereCenter, class BoundaryLineSet *BaseLine, atom *ThirdNode, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC) 2215 2186 { 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; 2359 2329 }; 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 */ 2341 bool 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 2360 2376 2361 2377 /** Finds the second point of starting triangle. … … 2370 2386 void Find_second_point_for_Tesselation(atom* a, atom* Candidate, Vector Oben, atom*& Opt_Candidate, double Storage[3], double RADIUS, LinkedCell *LC) 2371 2387 { 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; 2429 2443 }; 2430 2444 … … 2438 2452 void Tesselation::Find_starting_triangle(ofstream *out, molecule *mol, const double RADIUS, LinkedCell *LC) 2439 2453 { 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"; 2549 2562 }; 2550 2563 … … 2560 2573 */ 2561 2574 bool 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; 2722 2730 }; 2723 2731 … … 2732 2740 void Find_non_convex_border(ofstream *out, molecule* mol, class Tesselation *Tess, class LinkedCell *LCList, const char *filename, const double RADIUS) 2733 2741 { 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 bool flag = false;// marks whether we went once through all baselines without finding any without two triangles2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 baseline = Tess->LinesOnBoundary.begin();// restart if we reach end due to newly inserted lines2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 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"; 2798 2806 }; 2799 2807 -
src/boundary.hpp
r375b458 r51c910 27 27 template <typename T> void SetEndpointsOrdered(T endpoints[2], T endpoint1, T endpoint2) 28 28 { 29 30 31 32 33 34 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 } 36 36 }; 37 37 38 38 class BoundaryPointSet { 39 40 41 42 39 public: 40 BoundaryPointSet(); 41 BoundaryPointSet(atom *Walker); 42 ~BoundaryPointSet(); 43 43 44 44 void AddLine(class BoundaryLineSet *line); 45 45 46 47 48 49 46 LineMap lines; 47 int LinesCount; 48 atom *node; 49 int Nr; 50 50 }; 51 51 52 52 class BoundaryLineSet { 53 54 55 56 53 public: 54 BoundaryLineSet(); 55 BoundaryLineSet(class BoundaryPointSet *Point[2], int number); 56 ~BoundaryLineSet(); 57 57 58 58 void AddTriangle(class BoundaryTriangleSet *triangle); 59 59 60 61 62 63 60 class BoundaryPointSet *endpoints[2]; 61 TriangleMap triangles; 62 int TrianglesCount; 63 int Nr; 64 64 }; 65 65 66 66 class BoundaryTriangleSet { 67 68 69 70 67 public: 68 BoundaryTriangleSet(); 69 BoundaryTriangleSet(class BoundaryLineSet *line[3], int number); 70 ~BoundaryTriangleSet(); 71 71 72 72 void GetNormalVector(Vector &NormalVector); 73 73 74 75 76 77 74 class BoundaryPointSet *endpoints[3]; 75 class BoundaryLineSet *lines[3]; 76 Vector NormalVector; 77 int Nr; 78 78 }; 79 79 80 80 class Tesselation { 81 81 public: 82 82 83 84 83 Tesselation(); 84 ~Tesselation(); 85 85 86 87 88 89 90 91 92 93 94 bool CheckPresenceOfTriangle(ofstream *out, atom *Candidates[3]);95 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); 96 96 97 98 99 100 101 102 103 104 105 106 107 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; 108 108 }; 109 109 … … 120 120 void Find_next_suitable_point(class BoundaryTriangleSet *BaseTriangle, class BoundaryLineSet *BaseLine, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC); 121 121 122 123 122 #endif /*BOUNDARY_HPP_*/ -
src/builder.cpp
r375b458 r51c910 282 282 case 'a': 283 283 cout << Verbose(0) << "Centering atoms in config file on origin." << endl; 284 mol->CenterOrigin((ofstream *)&cout , &x);284 mol->CenterOrigin((ofstream *)&cout); 285 285 break; 286 286 case 'b': 287 287 cout << Verbose(0) << "Centering atoms in config file on center of gravity." << endl; 288 mol->Center Gravity((ofstream *)&cout, &x);288 mol->CenterPeriodic((ofstream *)&cout); 289 289 break; 290 290 case 'c': … … 295 295 } 296 296 mol->CenterEdge((ofstream *)&cout, &x); // make every coordinate positive 297 mol-> Translate(&y); // translate by boundary297 mol->Center.AddVector(&y); // translate by boundary 298 298 helper.CopyVector(&y); 299 299 helper.Scale(2.); … … 436 436 static void RemoveAtoms(molecule *mol) 437 437 { 438 atom *first, *second , *third;438 atom *first, *second; 439 439 int axis; 440 440 double tmp1, tmp2; … … 459 459 break; 460 460 case 'b': 461 third = mol->AskAtom("Enter number of atom as reference point: ");461 second = mol->AskAtom("Enter number of atom as reference point: "); 462 462 cout << Verbose(0) << "Enter radius: "; 463 463 cin >> tmp1; … … 467 467 first = second; 468 468 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 ... 470 470 mol->RemoveAtom(first); 471 471 } … … 634 634 static void ManipulateAtoms(periodentafel *periode, MoleculeListClass *molecules, config *configuration) 635 635 { 636 atom *first, *second, *third, *fourth; 637 Vector **atoms; 636 atom *first, *second; 638 637 molecule *mol = NULL; 639 638 Vector x,y,z,n; // coordinates for absolute point in cell volume 640 639 double *factor; // unit factor if desired 641 double a,b,c;642 640 double bond, min_bond; 643 641 char choice; // menu choice char … … 652 650 cout << Verbose(0) << "all else - go back" << endl; 653 651 cout << Verbose(0) << "===============================================" << endl; 654 if (molecules->NumberOfActiveMolecules() > 0)652 if (molecules->NumberOfActiveMolecules() > 1) 655 653 cout << Verbose(0) << "WARNING: There is more than one molecule active! Atoms will be added to each." << endl; 656 654 cout << Verbose(0) << "INPUT: "; … … 663 661 664 662 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) { 666 665 mol = *ListRunner; 667 666 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl; … … 671 670 672 671 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) { 674 674 mol = *ListRunner; 675 675 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl; … … 693 693 694 694 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) { 696 697 mol = *ListRunner; 697 698 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl; … … 709 710 710 711 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) { 712 714 mol = *ListRunner; 713 715 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl; … … 717 719 718 720 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) { 720 723 mol = *ListRunner; 721 724 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl; … … 725 728 726 729 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) { 728 732 int Z; 729 733 mol = *ListRunner; … … 749 753 static void ManipulateMolecules(periodentafel *periode, MoleculeListClass *molecules, config *configuration) 750 754 { 751 atom *first, *second, *third, *fourth; 752 Vector **atoms; 755 atom *first; 753 756 Vector x,y,z,n; // coordinates for absolute point in cell volume 754 double a,b,c;755 757 int j, axis, count, faktor; 756 758 char choice; // menu choice char 757 bool valid;758 759 molecule *mol = NULL; 759 760 element **Elements; … … 772 773 cout << Verbose(0) << "all else - go back" << endl; 773 774 cout << Verbose(0) << "===============================================" << endl; 774 if (molecules->NumberOfActiveMolecules() > 0)775 if (molecules->NumberOfActiveMolecules() > 1) 775 776 cout << Verbose(0) << "WARNING: There is more than one molecule active! Atoms will be added to each." << endl; 776 777 cout << Verbose(0) << "INPUT: "; … … 783 784 784 785 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) { 786 788 mol = *ListRunner; 787 789 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl; … … 841 843 842 844 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) { 844 847 mol = *ListRunner; 845 848 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl; … … 849 852 850 853 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) { 852 856 mol = *ListRunner; 853 857 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl; … … 857 861 858 862 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) { 860 865 mol = *ListRunner; 861 866 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl; … … 865 870 866 871 case 'o': // create the connection matrix 867 { 872 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) 873 if ((*ListRunner)->ActiveFlag) { 868 874 double bonddistance; 869 875 clock_t start,end; … … 879 885 880 886 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) { 882 889 mol = *ListRunner; 883 890 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl; 884 891 cout << Verbose(0) << "Enter translation vector." << endl; 885 892 x.AskPosition(mol->cell_size,0); 886 mol-> Translate((const Vector *)&x);893 mol->Center.AddVector((const Vector *)&x); 887 894 } 888 895 break; … … 906 913 { 907 914 char choice; // menu choice char 908 bool valid; 909 Vector Center; 915 Vector center; 910 916 int nr, count; 911 917 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; 917 920 cout << Verbose(0) << "c - create new molecule" << endl; 918 921 cout << Verbose(0) << "l - load molecule from xyz file" << endl; 919 922 cout << Verbose(0) << "n - change molecule's name" << endl; 920 923 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; 922 925 cout << Verbose(0) << "r - remove a molecule" << endl; 923 926 cout << Verbose(0) << "all else - go back" << endl; … … 935 938 break; 936 939 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, ¢er); 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: "; 942 971 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 } 965 974 break; 966 975 967 976 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 } 976 988 break; 977 989 978 990 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 } 991 1006 break; 992 1007 … … 995 1010 cin >> nr; 996 1011 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 } 1004 1018 break; 1005 1019 } … … 1014 1028 { 1015 1029 char choice; // menu choice char 1016 bool valid;1017 1030 1018 1031 cout << Verbose(0) << "===========MERGE MOLECULES=====================" << endl; 1032 cout << Verbose(0) << "a - simple add of one molecule to another" << endl; 1019 1033 cout << Verbose(0) << "e - embedding merge of two molecules" << endl; 1020 1034 cout << Verbose(0) << "m - multi-merge of all molecules" << endl; … … 1031 1045 break; 1032 1046 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 1033 1068 case 'e': 1069 cout << Verbose(0) << "Not implemented yet." << endl; 1034 1070 break; 1035 1071 1036 1072 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 } 1037 1091 break; 1038 1092 1039 1093 case 's': 1094 cout << Verbose(0) << "Not implemented yet." << endl; 1040 1095 break; 1041 1096 1042 1097 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 } 1043 1116 break; 1044 1117 } … … 1140 1213 molecule *mol = new molecule(periode); 1141 1214 1142 // merge all molecules in MoleculeListClass into this molecule1215 // translate each to its center and merge all molecules in MoleculeListClass into this molecule 1143 1216 int N = molecules->ListOfMolecules.size(); 1144 1217 int *src = new int(N); 1145 1218 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++) { 1147 1220 src[N++] = (*ListRunner)->IndexNr; 1221 (*ListRunner)->Translate(&(*ListRunner)->Center); 1222 } 1148 1223 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 } 1149 1231 1150 1232 cout << Verbose(0) << "Storing configuration ... " << endl; … … 1152 1234 mol->CalculateOrbitals(*configuration); 1153 1235 configuration->InitMaxMinStopStep = configuration->MaxMinStopStep = configuration->MaxPsiDouble; 1154 strcpy(filename, ConfigFileName);1155 1236 if (ConfigFileName != NULL) { // test the file name 1156 output.open(ConfigFileName, ios::trunc); 1237 strcpy(filename, ConfigFileName); 1238 output.open(filename, ios::trunc); 1157 1239 } else if (strlen(configuration->configname) != 0) { 1158 1240 strcpy(filename, configuration->configname); … … 1223 1305 * \return exit code (0 - successful, all else - something's wrong) 1224 1306 */ 1225 static int ParseCommandLineOptions(int argc, char **argv, MoleculeListClass *&molecules, periodentafel *&periode, config& configuration, char * &ConfigFileName, char *&PathToDatabases)1307 static int ParseCommandLineOptions(int argc, char **argv, MoleculeListClass *&molecules, periodentafel *&periode, config& configuration, char *ConfigFileName, char *&PathToDatabases) 1226 1308 { 1227 1309 Vector x,y,z,n; // coordinates for absolute point in cell volume … … 1242 1324 // simply create a new molecule, wherein the config file is loaded and the manipulation takes place 1243 1325 molecule *mol = new molecule(periode); 1326 mol->ActiveFlag = true; 1244 1327 molecules->insert(mol); 1245 1328 … … 1276 1359 cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl; 1277 1360 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; 1278 1362 cout << "\t-r\t\tConvert file from an old pcp syntax." << endl; 1279 1363 cout << "\t-R\t\tRemove all atoms out of sphere around a given one." << endl; … … 1337 1421 } else { 1338 1422 cout << "Empty configuration file." << endl; 1339 ConfigFileName = argv[1];1423 strcpy(ConfigFileName, argv[1]); 1340 1424 config_present = empty; 1341 1425 output.close(); … … 1343 1427 } else { 1344 1428 test.close(); 1345 ConfigFileName = argv[1];1429 strcpy(ConfigFileName, argv[1]); 1346 1430 cout << Verbose(1) << "Specified config file found, parsing ... "; 1347 1431 switch (configuration.TestSyntax(ConfigFileName, periode, mol)) { … … 1500 1584 LinkedCell LCList(mol, atof(argv[argptr])); // \NOTE not twice the radius?? 1501 1585 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()); 1503 1587 argptr+=2; 1504 1588 } … … 1521 1605 } 1522 1606 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; 1523 1617 case 'P': 1524 1618 ExitFlag = 1; … … 1529 1623 SaveFlag = true; 1530 1624 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)) 1532 1626 cout << Verbose(2) << "File not found." << endl; 1533 1627 else … … 1650 1744 ExitFlag = 1; 1651 1745 SaveFlag = true; 1652 cout << Verbose(1) << "Centering atoms in origin." << endl;1653 mol->Center Origin((ofstream *)&cout, &x);1746 cout << Verbose(1) << "Centering atoms on edge and setting box dimensions." << endl; 1747 mol->CenterEdge((ofstream *)&cout, &x); 1654 1748 mol->SetBoxDimension(&x); 1655 1749 break; … … 1831 1925 molecule *mol = NULL; 1832 1926 config configuration; 1833 double tmp1;1834 atom *first, *second;1835 1927 char choice; // menu choice char 1836 1928 Vector x,y,z,n; // coordinates for absolute point in cell volume 1837 bool valid; // flag if input was valid or not1838 1929 ifstream test; 1839 1930 ofstream output; 1840 1931 string line; 1841 char *ConfigFileName = NULL;1932 char ConfigFileName[MAXSTRINGSIZE]; 1842 1933 char *ElementsFileName = NULL; 1843 int Z; 1844 int j, axis, count, faktor; 1934 int j; 1845 1935 1846 1936 // =========================== PARSE COMMAND LINE OPTIONS ==================================== 1937 ConfigFileName[0] = '\0'; 1847 1938 j = ParseCommandLineOptions(argc, argv, molecules, periode, configuration, ConfigFileName, ElementsFileName); 1848 1939 if (j == 1) return 0; // just for -v and -h options … … 1861 1952 molecules->insert(mol); 1862 1953 } 1954 if (strlen(ConfigFileName) == 0) 1955 strcpy(ConfigFileName, DEFAULTCONFIG); 1956 1863 1957 1864 1958 // =========================== START INTERACTIVE SESSION ==================================== … … 1872 1966 cout << Verbose(0) << "============Menu===============================" << endl; 1873 1967 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; 1875 1969 cout << Verbose(0) << "g - globally manipulate atoms in molecule" << endl; 1876 1970 cout << Verbose(0) << "M - Merge molecules" << endl; … … 1891 1985 cout << "Enter index of molecule: "; 1892 1986 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; 1898 1990 } 1899 1991 break; -
src/config.cpp
r375b458 r51c910 13 13 config::config() 14 14 { 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; 85 108 }; 86 109 … … 90 113 config::~config() 91 114 { 92 93 94 95 96 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"); 97 120 }; 121 122 /** Readin of Thermostat related values from parameter file. 123 * \param *source parameter file 124 */ 125 void 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 98 197 99 198 /** Displays menu for editing each entry of the config file. … … 103 202 void config::Edit() 104 203 { 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 // 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 // 286 // 287 // 288 // 289 // 290 // 291 // 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 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'); 360 459 }; 361 460 … … 368 467 int config::TestSyntax(char *filename, periodentafel *periode, molecule *mol) 369 468 { 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 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; 385 484 } 386 485 … … 390 489 bool config::GetIsAngstroem() const 391 490 { 392 491 return (IsAngstroem == 1); 393 492 }; 394 493 … … 398 497 char * config::GetDefaultPath() const 399 498 { 400 499 return defaultpath; 401 500 }; 402 501 … … 407 506 void config::SetDefaultPath(const char *path) 408 507 { 409 508 strcpy(defaultpath, path); 410 509 }; 411 510 … … 415 514 void config::RetrieveConfigPathAndName(string filename) 416 515 { 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 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); 437 536 }; 438 537 … … 445 544 void config::Load(char *filename, periodentafel *periode, molecule *mol) 446 545 { 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); 767 871 }; 768 872 … … 774 878 void config::LoadOld(char *filename, periodentafel *periode, molecule *mol) 775 879 { 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 input >> AtomNo;// number of atoms943 input >> Z;// atomic number944 945 946 947 input >> b;// element mass948 949 cout << Verbose(1) << "AtomNo: " << AtomNo << "\tZ: " << Z << "\ta:" << a << "\tl:"<< l << "\b:" << b << "\tElement:" << elementhash[No] << "\t:" << endl;950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 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); 971 1075 }; 972 1076 … … 978 1082 bool config::Save(const char *filename, periodentafel *periode, molecule *mol) const 979 1083 { 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; 1078 1205 }; 1079 1206 … … 1085 1212 bool config::SaveMPQC(const char *filename, molecule *mol) const 1086 1213 { 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 *output << "\tname = \""<< basis << "\"" << endl;1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 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; 1195 1322 }; 1196 1323 … … 1204 1331 * \param name Name of value in file (at least 3 chars!) 1205 1332 * \param sequential 1 - do not reset file pointer to begin of file, 0 - set to beginning 1206 * 1207 * 1208 * 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!) 1209 1336 * \param xth Which among a number of parameters it is (in grid case it's row number as grid is read as a whole!) 1210 1337 * \param yth In grid case specifying column number, otherwise the yth \a name matching line … … 1217 1344 */ 1218 1345 int 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 variables1220 1221 1222 char *dummy1, *dummy, *free_dummy;// pointers in the line that is read in per step1223 1224 1225 1226 1227 1228 1229 1230 1231 int found = (type >= grid) ? 0 : (-yth + 1);// marks if yth parameter name was found1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 file->seekg(file_position, ios::beg);// rewind to start position1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 dummy = strchr(dummy1,'\t');// set dummy on first tab or space which ever's nearer1269 1270 dummy = strchr(dummy1, ' ');// if not found seek for space1271 while ((dummy != NULL) && ((*dummy == '\t') || (*dummy == ' ')))// skip some more tabs and spaces if necessary1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 file->seekg(file_position, ios::beg);// rewind to start position1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 while ((*dummy == '\t') || (*dummy == ' '))// skip interjacent tabs and spaces1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 dummy = strchr(dummy1, ' ');// if not found seek for space1342 1343 dummy = strchr(dummy1, '\n');// ... at line end then1344 if ((j < yth-1) && (type < 4)) {// check if xth value or not yet1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 file->seekg(file_position, ios::beg);// rewind to start position1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 file->seekg(file_position, ios::beg);// rewind to start position1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 strncpy((char *)value, dummy1, length);// copy as much1407 ((char *)value)[length] = '\0';// and set end marker1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 file->seekg(file_position, ios::beg);// rewind to start position1427 1428 1429 1430 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 1431 1558 } -
src/datacreator.cpp
r375b458 r51c910 19 19 bool OpenOutputFile(ofstream &output, const char *dir, const char *filename) 20 20 { 21 22 23 24 25 26 27 28 21 stringstream name; 22 name << dir << "/" << filename; 23 output.open(name.str().c_str(), ios::out); 24 if (output == NULL) { 25 cout << "Unable to open " << name.str() << " for writing, is directory correct?" << endl; 26 return false; 27 } 28 return true; 29 29 }; 30 30 … … 37 37 bool AppendOutputFile(ofstream &output, const char *dir, const char *filename) 38 38 { 39 40 41 42 43 44 45 46 39 stringstream name; 40 name << dir << "/" << filename; 41 output.open(name.str().c_str(), ios::app); 42 if (output == NULL) { 43 cout << "Unable to open " << name.str() << " for writing, is directory correct?" << endl; 44 return false; 45 } 46 return true; 47 47 }; 48 48 … … 56 56 bool CreateDataEnergyOrder(class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 57 57 { 58 59 60 61 62 63 64 65 output << "#Order\tFrag.No.\t" << Fragments.Header<< endl;66 67 68 69 for(int k=Fragments.ColumnCounter;k--;)70 71 72 73 for (int l=0;l<Fragments.ColumnCounter;l++)74 75 76 77 78 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; 79 79 }; 80 80 … … 89 89 bool CreateDataDeltaEnergyOrder(class EnergyMatrix &Energy, class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 90 90 { 91 92 93 94 95 96 97 98 output << "#Order\tFrag.No.\t" << Fragments.Header<< endl;99 100 101 102 103 for(int k=Fragments.ColumnCounter;k--;)104 105 106 107 for (int l=0;l<Fragments.ColumnCounter;l++)108 109 110 111 112 113 114 115 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; 116 116 }; 117 117 … … 126 126 bool CreateDataForcesOrder(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateForce)(class MatrixContainer &, int)) 127 127 { 128 129 130 131 132 133 134 135 output << "# Order\tFrag.No.\t" << Fragments.Header<< endl;136 137 138 139 140 141 for (int l=0;l<Fragments.ColumnCounter;l++)142 143 144 145 146 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; 147 147 }; 148 148 … … 158 158 bool CreateDataDeltaForcesOrder(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateForce)(class MatrixContainer &, int)) 159 159 { 160 161 162 163 164 165 166 167 output << "# Order\tFrag.No.\t" << Fragments.Header<< endl;168 169 170 171 172 173 for (int l=0;l<Fragments.ColumnCounter;l++)174 175 176 177 178 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; 179 179 }; 180 180 … … 190 190 bool CreateDataDeltaForcesOrderPerAtom(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 191 191 { 192 193 194 195 196 197 198 199 200 output << "# AtomNo\t" << Fragments.Header<< endl;201 202 203 204 205 206 207 208 209 for (int l=0;l<Fragments.ColumnCounter;l++) {210 211 212 213 214 215 } 216 // 217 218 // 219 // 220 221 222 223 224 225 226 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; 227 227 }; 228 228 … … 237 237 bool CreateDataForcesOrderPerAtom(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 238 238 { 239 stringstream filename; 240 ofstream output; 241 242 filename << prefix << ".dat"; 243 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 244 cout << msg << endl; 245 output << "# " << msg << ", created on " << datum; 246 output << "# AtomNo\t" << Fragments.Header << endl; 247 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 248 //cout << "Current order is " << BondOrder << "." << endl; 249 Fragments.SumSubForces(Fragments, KeySet, BondOrder, 1.); 250 // errors per atom 251 output << endl << "#Order\t" << BondOrder+1 << endl; 252 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) { 253 output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t"; 254 for (int l=0;l<Fragments.ColumnCounter;l++) 255 output << scientific << Fragments.Matrix[Fragments.MatrixCounter][ j ][l] << "\t"; 256 output << endl; 257 } 258 output << endl; 259 } 260 output.close(); 261 return true; 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 */ 274 bool 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 */ 312 bool 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 */ 356 bool 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; 262 382 }; 263 383 … … 266 386 bool CreateDataFragment(class MatrixContainer &Fragment, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateFragment)(class MatrixContainer &, int)) 267 387 { 268 269 270 271 272 273 274 275 output << "#Order\tFrag.No.\t" << Fragment.Header<< endl;276 277 278 279 280 for (int l=0;l<Fragment.ColumnCounter;l++)281 282 283 284 285 286 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; 287 407 }; 288 408 … … 294 414 void CreateMaxFragmentOrder(class MatrixContainer &Fragments, class KeySetsContainer &KeySet, int BondOrder) 295 415 { 296 297 298 299 for (int k=Fragments.ColumnCounter;k--;)300 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 } 304 424 }; 305 425 … … 311 431 void CreateMinFragmentOrder(class MatrixContainer &Fragments, class KeySetsContainer &KeySet, int BondOrder) 312 432 { 313 314 315 do {// first get a minimum value unequal to 0316 for (int k=Fragments.ColumnCounter;k--;)317 318 319 320 321 322 for (int k=Fragments.ColumnCounter;k--;)323 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 } 327 447 }; 328 448 … … 331 451 bool CreateDataFragmentOrder(class MatrixContainer &Fragment, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateFragmentOrder)(class MatrixContainer &, class KeySetsContainer &, int)) 332 452 { 333 334 335 336 337 338 339 340 output << "#Order\tFrag.No.\t" << Fragment.Header<< endl;341 342 343 344 345 346 for (int l=0;l<Fragment.ColumnCounter;l++)347 348 349 350 351 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; 352 472 }; 353 473 … … 358 478 void CreateEnergy(class MatrixContainer &Energy, int MatrixNumber) 359 479 { 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]; 362 482 }; 363 483 … … 369 489 void CreateMinimumForce(class MatrixContainer &Force, int MatrixNumber) 370 490 { 371 for (int l=Force.ColumnCounter;l--;)372 373 for (int l=5;l<Force.ColumnCounter;l+=3) {374 375 376 377 378 379 380 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m]= Force.Matrix[MatrixNumber][ k ][l+m];381 382 383 384 385 386 387 388 389 if ((fabs(tmp) > MYEPSILON) && (tmp < stored)) {// current force is greater than stored390 391 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m]= Force.Matrix[MatrixNumber][ k ][l+m];392 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 } 396 516 }; 397 517 … … 399 519 * Results are stored in the matrix ForceMatrix::MatrixCounter of \a Force. 400 520 * \param Force ForceMatrix class containing matrix values 401 521 * \param MatrixNumber the index for the ForceMatrix::matrix array 402 522 */ 403 523 void CreateMeanForce(class MatrixContainer &Force, int MatrixNumber) 404 524 { 405 406 for (int l=Force.ColumnCounter;l--;)407 408 for (int l=5;l<Force.ColumnCounter;l+=3) {409 410 411 412 413 414 415 416 417 418 419 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 } 421 541 }; 422 542 … … 428 548 void CreateMaximumForce(class MatrixContainer &Force, int MatrixNumber) 429 549 { 430 for (int l=5;l<Force.ColumnCounter;l+=3) {431 432 433 434 435 436 437 if (tmp > stored) {// current force is greater than stored438 439 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m]= Force.Matrix[MatrixNumber][ k ][l+m];440 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 } 444 564 }; 445 565 … … 450 570 void CreateSameForce(class MatrixContainer &Force, int MatrixNumber) 451 571 { 452 572 // does nothing 453 573 }; 454 574 … … 460 580 void CreateVectorSumForce(class MatrixContainer &Force, int MatrixNumber) 461 581 { 462 for (int l=Force.ColumnCounter;l--;)463 464 for (int l=0;l<Force.ColumnCounter;l++) {465 466 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 } 468 588 }; 469 589 … … 480 600 void 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) 481 601 { 482 483 484 485 486 487 488 489 490 491 492 493 494 495 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; 496 616 }; 497 617 … … 517 637 bool 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 *)) 518 638 { 519 520 521 522 523 524 525 526 527 528 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; 529 649 }; 530 650 … … 538 658 void AbsEnergyPlotLine(ofstream &output, class MatrixContainer &Energy, const char *prefix, const char *xargument, const char *uses) 539 659 { 540 stringstream line(Energy.Header);541 542 543 544 for (int i=2; i<= Energy.ColumnCounter;i++) {545 546 547 548 549 if (i != (Energy.ColumnCounter))550 551 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 } 553 673 }; 554 674 … … 562 682 void EnergyPlotLine(ofstream &output, class MatrixContainer &Energy, const char *prefix, const char *xargument, const char *uses) 563 683 { 564 stringstream line(Energy.Header);565 566 567 568 for (int i=1; i<= Energy.ColumnCounter;i++) {569 570 571 572 573 if (i != (Energy.ColumnCounter))574 575 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 } 577 697 }; 578 698 … … 586 706 void ForceMagnitudePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses) 587 707 { 588 stringstream line(Force.Header);589 590 591 592 593 594 595 596 for (int i=7; i< Force.ColumnCounter;i+=NDIM) {597 598 599 600 token.erase(token.length(), 1);// kill residual index char (the '0')601 602 if (i != (Force.ColumnCounter-1))603 604 605 606 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 } 608 728 }; 609 729 … … 617 737 void AbsFirstForceValuePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses) 618 738 { 619 stringstream line(Force.Header);620 621 622 623 624 625 626 627 for (int i=7; i< Force.ColumnCounter;i+=NDIM) {628 629 630 631 token.erase(token.length(), 1);// kill residual index char (the '0')632 633 if (i != (Force.ColumnCounter-1))634 635 636 637 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 } 639 759 }; 640 760 … … 648 768 void BoxesForcePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses) 649 769 { 650 stringstream line(Force.Header);651 652 653 654 655 656 657 658 659 for (int i=7; i< Force.ColumnCounter;i+=NDIM) {660 661 662 663 token.erase(token.length(), 1);// kill residual index char (the '0')664 665 if (i != (Force.ColumnCounter-1))666 667 668 669 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 } 671 791 }; 672 792 … … 680 800 void BoxesFirstForceValuePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses) 681 801 { 682 stringstream line(Force.Header);683 684 685 686 687 688 689 690 691 for (int i=7; i< Force.ColumnCounter;i+=NDIM) {692 693 694 695 token.erase(token.length(), 1);// kill residual index char (the '0')696 697 if (i != (Force.ColumnCounter-1))698 699 700 701 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 25 25 bool CreateDataForcesOrderPerAtom(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); 26 26 bool 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); 27 bool CreateDataDeltaForcesOrderPerAtom(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); 28 bool CreateDataHessianOrderPerAtom(class HessianMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); 29 bool CreateDataDeltaHessianOrderPerAtom(class HessianMatrix &Hessian, class HessianMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); 30 bool CreateDataDeltaFrobeniusOrderPerAtom(class HessianMatrix &Hessian, class HessianMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); 28 31 bool CreateDataFragment(class MatrixContainer &ForceFragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateForce)(class MatrixContainer &, int)); 29 32 bool 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 10 10 using namespace std; 11 11 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 18 27 #define VERSIONSTRING "v1.0" 19 28 … … 24 33 enum EdgeType { Undetermined, TreeEdge, BackEdge }; //!< edge type in a graph after Depth-First-Search analysis. 25 34 26 enum Shading { white, lightgray, darkgray, black }; 35 enum Shading { white, lightgray, darkgray, black }; //!< color in Breadth-First-Search analysis 27 36 28 //enum CutCyclicBond { KeepBond, 37 //enum CutCyclicBond { KeepBond, SaturateBond }; //!< Saturation scheme either atom- or bondwise 29 38 30 39 // Specifting whether a value in the parameter file must be specified or is optional 31 enum necessity { optional, 32 critical//!< parameter must be given or programme won't initiate33 40 enum necessity { optional, //!< parameter is optional, if not given sensible value is chosen 41 critical //!< parameter must be given or programme won't initiate 42 }; 34 43 35 44 // Specifying the status of the on command line given config file … … 43 52 44 53 // various standard filenames 45 #define DEFAULTCONFIG "main_pcp_linux" 46 #define CONVEXENVELOPE "ConvexEnvelope.dat" 47 #define KEYSETFILE "KeySets.dat" 48 #define ADJACENCYFILE "Adjacency.dat" 49 #define TEFACTORSFILE "TE-Factors.dat" 50 #define FORCESFILE "Forces-Factors.dat" 51 #define HCORRECTIONSUFFIX "Hcorrection.dat" 52 #define FITCONSTANTSUFFIX "FitConstant.dat" 53 #define SHIELDINGSUFFIX "sigma_all.csv" 54 #define SHIELDINGPASSUFFIX "sigma_all_PAS.csv" 55 #define ORDERATSITEFILE "OrderAtSite.dat" 56 #define ENERGYPERFRAGMENT "EnergyPerFragment" 57 #define FRAGMENTPREFIX "BondFragment" 58 #define STANDARDCONFIG "unknown.conf" 59 #define STANDARDELEMENTSDB "elements.db" 60 #define STANDARDVALENCEDB "valence.db" 61 #define STANDARDORBITALDB "orbitals.db" 62 #define STANDARDHBONDDISTANCEDB "Hbonddistance.db" 63 #define STANDARDHBONDANGLEDB "Hbondangle.db" 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 64 73 65 74 // some values … … 68 77 69 78 70 #define UPDATECOUNT 10 79 #define UPDATECOUNT 10 //!< update ten sites per BOSSANOVA interval 71 80 72 81 #endif /*DEFS_HPP_*/ -
src/ellipsoid.cpp
r375b458 r51c910 217 217 int PointsLeft = 0; 218 218 int PointsPicked = 0; 219 double value, threshold;220 219 int Nlower[NDIM], Nupper[NDIM]; 221 220 set<int> PickedAtomNrs; // ordered list of picked atoms … … 274 273 PickedAtomNrs.insert(index); 275 274 } 276 } while (PickedAtomNrs.size() < PointsToPick);275 } while (PickedAtomNrs.size() < (size_t) PointsToPick); 277 276 278 277 index = 0; // now go through all and pick those whose from PickedAtomsNr -
src/graph.cpp
r375b458 r51c910 7 7 using namespace std; 8 8 9 #include "graph.hpp" 9 10 10 #include <iostream> 11 #include <list> 12 #include <vector> 11 /***************************************** Implementations for graph classes ********************************/ 13 12 14 /***************************************** Functions for class graph ********************************/ 13 /** Constructor of class Graph. 14 */ 15 Graph::Graph() 16 { 17 }; 15 18 19 /** Destructor of class Graph. 20 * Destructor does release memory for nodes and edges contained in its lists as well. 21 */ 22 Graph::~Graph() 23 { 24 }; 16 25 26 /** Constructor of class SubGraph. 27 */ 28 SubGraph::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 */ 35 SubGraph::~SubGraph() 36 { 37 }; 38 39 /** Constructor of class Node. 40 */ 41 Node::Node() 42 { 43 }; 44 45 /** Destructor of class Node. 46 */ 47 Node::~Node() 48 { 49 }; 50 51 /** Constructor of class Edge. 52 */ 53 Edge::Edge() 54 { 55 }; 56 57 /** Destructor of class Edge. 58 */ 59 Edge::~Edge() 60 { 61 }; 62 -
src/helpers.cpp
r375b458 r51c910 71 71 void * ReAlloc(void * OldPointer, size_t size, const char* output) 72 72 { 73 74 75 76 77 78 79 80 81 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); 82 82 }; 83 83 -
src/joiner.cpp
r375b458 r51c910 17 17 int main(int argc, char **argv) 18 18 { 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; 178 244 }; 179 245 -
src/moleculelist.cpp
r375b458 r51c910 35 35 * \return true - add successful 36 36 */ 37 boolMoleculeListClass::insert(molecule *mol)37 void MoleculeListClass::insert(molecule *mol) 38 38 { 39 39 mol->IndexNr = MaxIndex++; … … 124 124 void MoleculeListClass::Enumerate(ofstream *out) 125 125 { 126 int i=1;127 126 element* Elemental = NULL; 128 127 atom *Walker = NULL; 129 128 int Counts[MAX_ELEMENTS]; 129 double size=0; 130 Vector Origin; 130 131 131 132 // header 132 *out << "Index\tName\t No.Atoms\tformula" << endl;133 *out << "Index\tName\t\tAtoms\tFormula\tCenter\tSize" << endl; 133 134 cout << Verbose(0) << "-----------------------------------------------" << endl; 134 135 if (ListOfMolecules.size() == 0) 135 136 *out << "\tNone" << endl; 136 137 else { 138 Origin.Zero(); 137 139 for (MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++) { 138 140 // reset element counts 139 141 for (int j = 0; j<MAX_ELEMENTS;j++) 140 142 Counts[j] = 0; 141 // count atoms per element 143 // count atoms per element and determine size of bounding sphere 144 size=0.; 142 145 Walker = (*ListRunner)->start; 143 146 while (Walker->next != (*ListRunner)->end) { 144 147 Walker = Walker->next; 145 148 Counts[Walker->type->Z]++; 149 if (Walker->x.DistanceSquared(&Origin) > size) 150 size = Walker->x.DistanceSquared(&Origin); 146 151 } 147 152 // output Index, Name, number of atoms, chemical formula 148 153 *out << ((*ListRunner)->ActiveFlag ? "*" : " ") << (*ListRunner)->IndexNr << "\t" << (*ListRunner)->name << "\t\t" << (*ListRunner)->AtomCount << "\t"; 149 154 Elemental = (*ListRunner)->elemente->end; 150 while(Elemental != (*ListRunner)->elemente->start) {155 while(Elemental->previous != (*ListRunner)->elemente->start) { 151 156 Elemental = Elemental->previous; 152 157 if (Counts[Elemental->Z] != 0) 153 158 *out << Elemental->symbol << Counts[Elemental->Z]; 154 159 } 155 *out << endl; 160 // Center and size 161 *out << "\t" << (*ListRunner)->Center << "\t" << sqrt(size) << endl; 156 162 } 157 163 } … … 164 170 molecule * MoleculeListClass::ReturnIndex(int index) 165 171 { 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; 173 176 }; 174 177 … … 523 526 524 527 // open file for the force factors 525 *out << Verbose(1) << "Saving 528 *out << Verbose(1) << "Saving force factors ... "; 526 529 line << path << "/" << FRAGMENTPREFIX << FORCESFILE; 527 530 ForcesFile.open(line.str().c_str(), ios::out); … … 565 568 * \param *configuration standard configuration to attach atoms in fragment molecule to. 566 569 * \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 567 572 * \return true - success (each file was written), false - something went wrong. 568 573 */ 569 bool MoleculeListClass::OutputConfigForListOfFragments(ofstream *out, 570 config *configuration, int *SortIndex) 574 bool MoleculeListClass::OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex) 571 575 { 572 576 ofstream outputFragment; … … 691 695 MoleculeLeafClass::MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf = NULL) 692 696 { 693 // 694 // 695 // 696 // 697 // 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; 698 702 Leaf = NULL; 699 703 previous = PreviousLeaf; … … 711 715 MoleculeLeafClass::~MoleculeLeafClass() 712 716 { 713 // 714 // 715 // 716 // 717 // 718 // 719 // 720 // 721 // 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 // } 723 727 // remove the leaf itself 724 728 if (Leaf != NULL) { … … 729 733 if (previous != NULL) 730 734 previous->next = next; 731 // 732 // 733 // NextLeaf->UpLeaf = UpLeaf;// either null as we are top level or the upleaf of the first node734 // 735 // UpLeaf->DownLeaf = NextLeaf;// either null as we are only leaf or NextLeaf if we are just the first736 // 737 // 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; 738 742 if (next != NULL) // are we last in list 739 743 next->previous = previous; -
src/molecules.cpp
r375b458 r51c910 63 63 cell_size[1] = cell_size[3] = cell_size[4]= 0.; 64 64 strcpy(name,"none"); 65 IndexNr = -1; 66 ActiveFlag = false; 65 67 }; 66 68 … … 602 604 * \param *filename filename 603 605 */ 604 void molecule::SetNameFromFilename(c har *filename)606 void molecule::SetNameFromFilename(const char *filename) 605 607 { 606 608 int length = 0; 607 609 char *molname = strrchr(filename, '/')+sizeof(char); // search for filename without dirs 608 char *endname = str rchr(filename, '.');610 char *endname = strchr(molname, '.'); 609 611 if ((endname == NULL) || (endname < molname)) 610 612 length = strlen(molname); … … 612 614 length = strlen(molname) - strlen(endname); 613 615 strncpy(name, molname, length); 616 name[length]='\0'; 614 617 }; 615 618 … … 668 671 max->Scale(0.5); 669 672 Translate(max); 673 Center.Zero(); 670 674 } 671 675 … … 707 711 max->AddVector(min); 708 712 Translate(min); 713 Center.Zero(); 709 714 } 710 715 delete(min); … … 716 721 * \param *center return vector for translation vector 717 722 */ 718 void molecule::CenterOrigin(ofstream *out , Vector *center)723 void molecule::CenterOrigin(ofstream *out) 719 724 { 720 725 int Num = 0; 721 726 atom *ptr = start->next; // start at first in list 722 727 723 for(int i=NDIM;i--;) // zero center vector 724 center->x[i] = 0.; 728 Center.Zero(); 725 729 726 730 if (ptr != end) { //list not empty? … … 728 732 ptr = ptr->next; 729 733 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(); 734 739 } 735 740 }; … … 796 801 * \param *center return vector for translation vector 797 802 */ 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 } 803 void 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 */ 812 void molecule::CenterAtVector(ofstream *out, Vector *newcenter) 813 { 814 Center.CopyVector(newcenter); 807 815 }; 808 816 … … 853 861 854 862 /** Determines center of molecule (yet not considering atom masses). 855 * \param Center reference to return vector856 */ 857 void molecule::Determine Center(Vector &Center)863 * \param center reference to return vector 864 */ 865 void molecule::DeterminePeriodicCenter(Vector ¢er) 858 866 { 859 867 atom *Walker = start; … … 865 873 866 874 do { 867 Center.Zero();875 center.Zero(); 868 876 flag = true; 869 877 while (Walker->next != end) { … … 892 900 Testvector.AddVector(&Translationvector); 893 901 Testvector.MatrixMultiplication(matrix); 894 Center.AddVector(&Testvector);902 center.AddVector(&Testvector); 895 903 cout << Verbose(1) << "vector is: "; 896 904 Testvector.Output((ofstream *)&cout); … … 905 913 Testvector.AddVector(&Translationvector); 906 914 Testvector.MatrixMultiplication(matrix); 907 Center.AddVector(&Testvector);915 center.AddVector(&Testvector); 908 916 cout << Verbose(1) << "Hydrogen vector is: "; 909 917 Testvector.Output((ofstream *)&cout); … … 916 924 } while (!flag); 917 925 Free((void **)&matrix, "molecule::DetermineCenter: *matrix"); 918 Center.Scale(1./(double)AtomCount);926 center.Scale(1./(double)AtomCount); 919 927 }; 920 928 … … 929 937 Vector *CenterOfGravity = DetermineCenterOfGravity(out); 930 938 931 Center Gravity(out, CenterOfGravity);939 CenterAtVector(out, CenterOfGravity); 932 940 933 941 // reset inertia tensor … … 1025 1033 }; 1026 1034 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 */ 1054 double 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 1181 void 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 */ 1230 double 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 */ 1407 void 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 */ 1433 bool 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 1027 1503 /** Parses nuclear forces from file and performs Verlet integration. 1028 1504 * Note that we assume the parsed forces to be in atomic units (hence, if coordinates are in angstroem, we 1029 1505 * have to transform them). 1030 1506 * This adds a new MD step to the config file. 1507 * \param *out output stream for debugging 1031 1508 * \param *file filename 1509 * \param config structure with config::Deltat, config::IsAngstroem, config::DoConstrained 1032 1510 * \param delta_t time step width in atomic units 1033 1511 * \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() 1034 1513 * \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 */ 1516 bool molecule::VerletForceIntegration(ofstream *out, char *file, config &configuration) 1517 { 1039 1518 atom *walker = NULL; 1040 int AtomNo;1041 1519 ifstream input(file); 1042 1520 string token; 1043 1521 stringstream item; 1044 double a, IonMass;1522 double IonMass, Vector[NDIM], ConstrainedPotentialEnergy, ActualTemp; 1045 1523 ForceMatrix Force; 1046 Vector tmpvector;1047 1524 1048 1525 CountElements(); // make sure ElementsInMolecule is up to date … … 1062 1539 } 1063 1540 // 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 1074 1560 // 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 */ 1646 void 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; 1082 1671 walker = start; 1083 1672 while (walker->next != end) { // go through every atom of this element 1084 1673 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]; 1092 1680 } 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); 1099 1734 } 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]; 1114 1754 } 1115 1755 } 1116 1756 } 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. 1145 1796 * \param n[] alignment vector. 1146 1797 */ … … 1800 2451 Vector x; 1801 2452 int FalseBondDegree = 0; 1802 2453 1803 2454 BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem); 1804 2455 *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl; … … 3043 3694 while (MolecularWalker->next != NULL) { 3044 3695 MolecularWalker = MolecularWalker->next; 3696 *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3045 3697 LocalBackEdgeStack = new StackClass<bond *> (MolecularWalker->Leaf->BondCount); 3046 3698 // // check the list of local atoms for debugging … … 3058 3710 delete(LocalBackEdgeStack); 3059 3711 } 3060 3712 3061 3713 // ===== 3. if structure still valid, parse key set file and others ===== 3062 3714 FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList); … … 3064 3716 // ===== 4. check globally whether there's something to do actually (first adaptivity check) 3065 3717 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 ===== 3069 3721 Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true); 3070 3722 … … 3101 3753 delete(ParsedFragmentList); 3102 3754 delete[](MinimumRingSize); 3103 3755 3104 3756 3105 3757 // ==================================== End of FRAGMENTATION ============================================ … … 3194 3846 atom *Walker = NULL, *OtherAtom = NULL; 3195 3847 ReferenceStack->Push(Binder); 3196 3848 3197 3849 do { // go through all bonds and push local ones 3198 3850 Walker = ListOfLocalAtoms[Binder->leftatom->nr]; // get one atom in the reference molecule … … 3664 4316 }; 3665 4317 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 /* 4332 MoleculeListClass * 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 3666 4481 /** Structure containing all values in power set combination generation. 3667 4482 */ … … 4495 5310 if (result) { 4496 5311 *out << Verbose(5) << "Calculating Centers of Gravity" << endl; 4497 Determine Center(CenterOfGravity);4498 OtherMolecule->Determine Center(OtherCenterOfGravity);5312 DeterminePeriodicCenter(CenterOfGravity); 5313 OtherMolecule->DeterminePeriodicCenter(OtherCenterOfGravity); 4499 5314 *out << Verbose(5) << "Center of Gravity: "; 4500 5315 CenterOfGravity.Output(out); -
src/molecules.hpp
r375b458 r51c910 10 10 11 11 // 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> 12 16 #include <gsl/gsl_multimin.h> 13 17 #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> 17 19 18 20 // STL headers … … 76 78 struct KeyCompare 77 79 { 78 80 bool operator() (const KeySet SubgraphA, const KeySet SubgraphB) const; 79 81 }; 80 82 81 83 struct Trajectory 82 84 { 83 vector<Vector> R;//!< position vector84 vector<Vector> U;//!< velocity vector85 vector<Vector> F;//!< last force vector86 atom *ptr;//!< pointer to atom whose trajectory we contain87 }; 88 89 //bool operator < (KeySet SubgraphA, KeySet SubgraphB); 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) 90 92 inline 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); 93 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter); // Insert all KeySet's in a Graph into another Graph 92 94 int CompareDoubles (const void * a, const void * b); 93 95 … … 97 99 98 100 // 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]) 100 #define RDET2(a0,a1,a2,a3) ((a0)*(a3)-(a1)*(a2)) 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 101 103 102 104 … … 104 106 */ 105 107 struct LSQ_params { 106 107 108 Vector **vectors; 109 int num; 108 110 }; 109 111 … … 113 115 */ 114 116 struct lsq_params { 115 116 117 117 gsl_vector *x; 118 const molecule *mol; 119 element *type; 118 120 }; 119 121 … … 122 124 */ 123 125 class atom { 124 125 Vector x;//!< coordinate array of atom, giving position within cell126 Vector v;//!< velocity array of atom127 element *type;//!< pointing to element128 129 atom *next;//!< next atom in molecule list130 atom *father;//!< In many-body bond order fragmentations points to originating atom131 132 char *Name;//!< unique name used during many-body bond-order fragmentation133 int FixedIon;//!< config variable that states whether forces act on the ion or not134 int *sort;//!< sort criteria135 int nr;//!< continuous, unique number136 int GraphNr;//!< unique number, given in DepthFirstSearchAnalysis()137 138 139 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 not143 144 145 146 147 148 149 150 151 152 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 157 ostream & operator << (ostream &ost, const atom &a); 156 158 157 159 /** Bonds between atoms. … … 161 163 */ 162 164 class 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 197 ostream & operator << (ostream &ost, const bond &b); 195 198 196 199 class MoleculeLeafClass; 200 201 202 #define MaxThermostats 6 //!< maximum number of thermostat entries in Ions#ThermostatNames and Ions#ThermostatImplemented 203 enum thermostats { None, Woodcock, Gaussian, Langevin, Berendsen, NoseHoover }; //!< Thermostat names for output 204 197 205 198 206 /** The complete molecule. … … 200 208 */ 201 209 class 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 ¢er); 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 ¢er); 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 333 348 }; 334 349 … … 336 351 */ 337 352 class MoleculeListClass { 338 339 340 341 342 343 344 345 346 347 boolinsert(molecule *mol);348 349 350 351 352 353 354 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 355 370 bool SimpleMerge(molecule *mol, molecule *srcmol); 356 371 bool SimpleAdd(molecule *mol, molecule *srcmol); … … 360 375 bool EmbedMerge(molecule *mol, molecule *srcmol); 361 376 362 377 private: 363 378 }; 364 379 … … 368 383 */ 369 384 class MoleculeLeafClass { 370 371 molecule *Leaf;//!< molecule of this leaf372 //MoleculeLeafClass *UpLeaf;//!< Leaf one level up373 //MoleculeLeafClass *DownLeaf;//!< First leaf one level down374 MoleculeLeafClass *previous;//!< Previous leaf on this level375 MoleculeLeafClass *next;//!< Next leaf on this level376 377 378 379 380 381 382 383 384 385 386 387 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; 388 403 }; 389 404 … … 392 407 */ 393 408 class 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); 480 504 }; 481 505 -
src/parser.cpp
r375b458 r51c910 24 24 bool FilePresent(const char *filename, bool test) 25 25 { 26 27 28 29 30 31 32 33 34 35 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; 36 36 }; 37 37 … … 43 43 bool TestParams(int argc, char **argv) 44 44 { 45 46 47 48 49 45 ifstream input; 46 stringstream line; 47 48 line << argv[1] << FRAGMENTPREFIX << KEYSETFILE; 49 return FilePresent(line.str().c_str(), false); 50 50 }; 51 51 … … 55 55 */ 56 56 MatrixContainer::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; 65 67 }; 66 68 … … 68 70 */ 69 71 MatrixContainer::~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 */ 106 bool 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 }; 95 135 96 136 /** Parsing a number of matrices. 97 * 98 * 99 * 100 * 101 * 102 * 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 103 143 * \param *name directory with files 104 144 * \param skiplines number of inital lines to skip … … 109 149 bool MatrixContainer::ParseMatrix(const char *name, int skiplines, int skipcolumns, int MatrixNr) 110 150 { 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; 190 231 }; 191 232 … … 193 234 * -# First, count the number of matrices by counting lines in KEYSETFILE 194 235 * -# Then, 195 * 196 * 197 * 198 * 199 * 200 * 201 * 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 202 243 * -# Finally, allocate one additional matrix (\a MatrixCounter) containing combined or temporary values 203 244 * \param *name directory with files … … 210 251 bool MatrixContainer::ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns) 211 252 { 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; 251 296 }; 252 297 253 298 /** Allocates and resets the memory for a number \a MCounter of matrices. 254 * \param * GivenHeader Header line299 * \param **GivenHeader Header line for each matrix 255 300 * \param MCounter number of matrices 256 301 * \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 */ 305 bool 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; 279 325 }; 280 326 … … 284 330 bool MatrixContainer::ResetMatrix() 285 331 { 286 287 288 for(int k=ColumnCounter;k--;)289 290 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; 291 337 }; 292 338 … … 296 342 double MatrixContainer::FindMaxValue() 297 343 { 298 299 300 301 for(int k=ColumnCounter;k--;)302 303 304 305 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; 306 352 return max; 307 353 }; … … 312 358 double MatrixContainer::FindMinValue() 313 359 { 314 315 316 317 for(int k=ColumnCounter;k--;)318 319 320 321 322 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; 323 369 }; 324 370 … … 330 376 bool MatrixContainer::SetLastMatrix(double value, int skipcolumns) 331 377 { 332 333 for(int k=skipcolumns;k<ColumnCounter;k++)334 335 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; 336 382 }; 337 383 … … 343 389 bool MatrixContainer::SetLastMatrix(double **values, int skipcolumns) 344 390 { 345 346 for(int k=skipcolumns;k<ColumnCounter;k++)347 348 349 }; 350 351 /** Sums the en ergy 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. 352 398 * 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. 354 400 * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order 355 401 * \param Order bond order … … 358 404 bool MatrixContainer::SumSubManyBodyTerms(class MatrixContainer &MatrixValues, class KeySetsContainer &KeySet, int Order) 359 405 { 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 cerr << "In fragment No. " << KeySet.OrderSet[Order][CurrentFragment]<< " current force index " << m << " is greater than " << RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ] << "!" << endl;383 384 385 386 for(int l=ColumnCounter;l--;) // then adds/subtract each column 387 388 389 for(int l=ColumnCounter;l--;)390 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 397 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 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; 405 451 }; 406 452 … … 412 458 bool MatrixContainer::WriteTotalFragments(const char *name, const char *prefix) 413 459 { 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 output << Header<< endl;429 430 for(int k=0;k<ColumnCounter;k++)431 432 433 434 435 436 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; 437 483 }; 438 484 … … 445 491 bool MatrixContainer::WriteLastMatrix(const char *name, const char *prefix, const char *suffix) 446 492 { 447 448 449 450 451 452 453 454 455 456 457 output << Header<< endl;458 459 for(int k=0;k<ColumnCounter;k++)460 461 462 463 464 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; 465 511 }; 466 512 … … 473 519 bool EnergyMatrix::ParseIndices() 474 520 { 475 476 477 478 479 480 481 482 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; 483 529 }; 484 530 485 531 /** Sums the energy with each factor and put into last element of \a EnergyMatrix::Matrix. 486 532 * 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. 488 534 * \param CorrectionFragments MatrixContainer with hydrogen saturation correction per fragments 489 535 * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order … … 494 540 bool EnergyMatrix::SumSubEnergy(class EnergyMatrix &Fragments, class EnergyMatrix *CorrectionFragments, class KeySetsContainer &KeySet, int Order, double sign) 495 541 { 496 497 498 499 500 for(int k=ColumnCounter;k--;)501 502 503 504 505 for(int k=ColumnCounter;k--;)506 507 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; 508 554 }; 509 555 … … 518 564 bool EnergyMatrix::ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns) 519 565 { 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; 542 592 }; 543 593 … … 550 600 bool ForceMatrix::ParseIndices(char *name) 551 601 { 552 553 554 555 556 557 558 559 560 561 //cout << "Opening " << line.str() << " ... "<< input << endl;562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 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; 587 637 }; 588 638 589 639 590 640 /** 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. 592 642 * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order 593 643 * \param Order bond order 594 * 644 * \param sign +1 or -1 595 645 * \return true if summing was successful 596 646 */ 597 647 bool ForceMatrix::SumSubForces(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign) 598 648 { 599 600 601 602 603 604 605 606 607 608 609 610 611 for(int k=2;k<ColumnCounter;k++)612 613 614 615 616 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; 617 667 }; 618 668 … … 628 678 bool ForceMatrix::ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns) 629 679 { 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 */ 737 bool 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 */ 784 bool 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 */ 816 HessianMatrix::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 */ 828 bool 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 */ 904 bool 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; 673 953 }; 674 954 … … 678 958 */ 679 959 KeySetsContainer::KeySetsContainer() { 680 681 682 683 684 685 960 KeySets = NULL; 961 AtomCounter = NULL; 962 FragmentCounter = 0; 963 Order = 0; 964 FragmentsPerOrder = 0; 965 OrderSet = NULL; 686 966 }; 687 967 … … 689 969 */ 690 970 KeySetsContainer::~KeySetsContainer() { 691 692 693 694 695 696 697 698 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"); 699 979 }; 700 980 … … 706 986 */ 707 987 bool KeySetsContainer::ParseKeySets(const char *name, const int *ACounter, const int FCounter) { 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 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; 746 1026 }; 747 1027 … … 751 1031 bool KeySetsContainer::ParseManyBodyTerms() 752 1032 { 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 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; 807 1087 }; 808 1088 … … 814 1094 bool KeySetsContainer::Contains(const int GreaterSet, const int SmallerSet) 815 1095 { 816 817 818 819 820 821 822 823 824 825 826 827 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; 828 1108 }; 829 1109 -
src/parser.hpp
r375b458 r51c910 19 19 20 20 #define EnergySuffix ".energy.all" 21 #define EnergyFragmentSuffix ".energyfragment.all" 22 #define ForcesSuffix ".forces.all" 23 #define ForceFragmentSuffix ".forcefragment.all" 21 24 #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" 23 29 #define ShieldingSuffix ".sigma_all.csv" 24 30 #define ShieldingPASSuffix ".sigma_all_PAS.csv" 25 31 #define ShieldingFragmentSuffix ".sigma_all_fragment.all" 26 32 #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" 27 37 #define TimeSuffix ".speed" 28 #define EnergyFragmentSuffix ".energyfragment.all"29 #define HcorrectionFragmentSuffix ".Hcorrectionfragment.all"30 #define ForceFragmentSuffix ".forcefragment.all"31 #define OrderSuffix ".Order"32 38 33 39 // ======================================= FUNCTIONS ========================================== … … 40 46 41 47 class 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); 66 73 }; 67 74 … … 69 76 70 77 class EnergyMatrix : public MatrixContainer { 71 72 73 74 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); 75 82 }; 76 83 … … 78 85 79 86 class 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 95 class 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; 84 105 }; 85 106 … … 87 108 88 109 class KeySetsContainer { 89 90 91 92 93 94 95 110 public: 111 int **KeySets; 112 int *AtomCounter; 113 int FragmentCounter; 114 int Order; 115 int *FragmentsPerOrder; 116 int **OrderSet; 96 117 97 98 118 KeySetsContainer(); 119 ~KeySetsContainer(); 99 120 100 101 102 121 bool ParseKeySets(const char *name, const int *ACounter, const int FCounter); 122 bool ParseManyBodyTerms(); 123 bool Contains(const int GreaterSet, const int SmallerSet); 103 124 }; 104 125 -
src/periodentafel.cpp
r375b458 r51c910 16 16 periodentafel::periodentafel() 17 17 { 18 19 20 21 22 23 18 start = new element; 19 end = new element; 20 start->previous = NULL; 21 start->next = end; 22 end->previous = start; 23 end->next = NULL; 24 24 }; 25 25 … … 29 29 periodentafel::~periodentafel() 30 30 { 31 32 33 31 CleanupPeriodtable(); 32 delete(end); 33 delete(start); 34 34 }; 35 35 … … 40 40 bool periodentafel::AddElement(element *pointer) 41 41 { 42 43 44 45 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); 46 46 }; 47 47 … … 52 52 bool periodentafel::RemoveElement(element *pointer) 53 53 { 54 54 return remove(pointer, start, end); 55 55 }; 56 56 … … 60 60 bool periodentafel::CleanupPeriodtable() 61 61 { 62 62 return cleanup(start,end); 63 63 }; 64 64 … … 70 70 element * periodentafel::FindElement(int Z) 71 71 { 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 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); 87 87 }; 88 88 … … 94 94 element * periodentafel::FindElement(char *shorthand) const 95 95 { 96 element *walker =periodentafel::start;97 98 99 100 101 102 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); 103 103 }; 104 104 … … 107 107 element * periodentafel::AskElement() 108 108 { 109 110 111 112 113 114 walker = this->FindElement(Z);// give type115 116 109 element *walker = NULL; 110 int Z; 111 do { 112 cout << Verbose(0) << "Atomic number Z: "; 113 cin >> Z; 114 walker = this->FindElement(Z); // give type 115 } while (walker == NULL); 116 return walker; 117 117 }; 118 118 … … 122 122 bool periodentafel::Output(ofstream *output) const 123 123 { 124 125 126 127 128 129 130 131 132 133 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; 134 134 }; 135 135 … … 140 140 bool periodentafel::Checkout(ofstream *output, const int *checkliste) const 141 141 { 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 142 element *walker = start; 143 bool result = true; 144 int No = 1; 145 146 if (output != NULL) { 147 *output << "# Ion type data (PP = PseudoPotential, Z = atomic number)" << endl; 148 *output << "#Ion_TypeNr.\tAmount\tZ\tRGauss\tL_Max(PP)L_Loc(PP)IonMass\t# chemical name, symbol" << endl; 149 while (walker->next != end) { 150 walker = walker->next; 151 if ((walker != NULL) && (walker->Z > 0) && (walker->Z < MAX_ELEMENTS) && (checkliste[walker->Z])) { 152 walker->No = No; 153 result = result && walker->Checkout(output, No++, checkliste[walker->Z]); 154 } 155 } 156 return result; 157 } else 158 return false; 159 159 }; 160 160 … … 164 164 bool periodentafel::LoadPeriodentafel(char *path) 165 165 { 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 cout <<"Parsed elements:";182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 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; 299 299 }; 300 300 … … 303 303 bool periodentafel::StorePeriodentafel(char *path) const 304 304 { 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 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 22 22 ostream& operator<<(ostream& ost,const Verbose& m) 23 23 { 24 24 return m.print(ost); 25 25 }; 26 26 … … 33 33 ostream& Binary::print (ostream &ost) const 34 34 { 35 36 37 38 39 40 41 42 43 44 45 46 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; 47 47 }; 48 48 … … 56 56 ostream& operator<<(ostream& ost,const Binary& m) 57 57 { 58 58 return m.print(ost); 59 59 };
Note:
See TracChangeset
for help on using the changeset viewer.