Changeset 437922
- Timestamp:
- Jul 23, 2009, 12:14:13 PM (16 years ago)
- Branches:
- Action_Thermostats, Add_AtomRandomPerturbation, Add_FitFragmentPartialChargesAction, Add_RotateAroundBondAction, Add_SelectAtomByNameAction, Added_ParseSaveFragmentResults, AddingActions_SaveParseParticleParameters, Adding_Graph_to_ChangeBondActions, Adding_MD_integration_tests, Adding_ParticleName_to_Atom, Adding_StructOpt_integration_tests, AtomFragments, Automaking_mpqc_open, AutomationFragmentation_failures, Candidate_v1.5.4, Candidate_v1.6.0, Candidate_v1.6.1, ChangeBugEmailaddress, ChangingTestPorts, ChemicalSpaceEvaluator, CombiningParticlePotentialParsing, Combining_Subpackages, Debian_Package_split, Debian_package_split_molecuildergui_only, Disabling_MemDebug, Docu_Python_wait, EmpiricalPotential_contain_HomologyGraph, EmpiricalPotential_contain_HomologyGraph_documentation, Enable_parallel_make_install, Enhance_userguide, Enhanced_StructuralOptimization, Enhanced_StructuralOptimization_continued, Example_ManyWaysToTranslateAtom, Exclude_Hydrogens_annealWithBondGraph, FitPartialCharges_GlobalError, Fix_BoundInBox_CenterInBox_MoleculeActions, Fix_ChargeSampling_PBC, Fix_ChronosMutex, Fix_FitPartialCharges, Fix_FitPotential_needs_atomicnumbers, Fix_ForceAnnealing, Fix_IndependentFragmentGrids, Fix_ParseParticles, Fix_ParseParticles_split_forward_backward_Actions, Fix_PopActions, Fix_QtFragmentList_sorted_selection, Fix_Restrictedkeyset_FragmentMolecule, Fix_StatusMsg, Fix_StepWorldTime_single_argument, Fix_Verbose_Codepatterns, Fix_fitting_potentials, Fixes, ForceAnnealing_goodresults, ForceAnnealing_oldresults, ForceAnnealing_tocheck, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_continued, ForceAnnealing_with_BondGraph_continued_betteresults, ForceAnnealing_with_BondGraph_contraction-expansion, FragmentAction_writes_AtomFragments, FragmentMolecule_checks_bonddegrees, GeometryObjects, Gui_Fixes, Gui_displays_atomic_force_velocity, ImplicitCharges, IndependentFragmentGrids, IndependentFragmentGrids_IndividualZeroInstances, IndependentFragmentGrids_IntegrationTest, IndependentFragmentGrids_Sole_NN_Calculation, JobMarket_RobustOnKillsSegFaults, JobMarket_StableWorkerPool, JobMarket_unresolvable_hostname_fix, MoreRobust_FragmentAutomation, ODR_violation_mpqc_open, PartialCharges_OrthogonalSummation, PdbParser_setsAtomName, PythonUI_with_named_parameters, QtGui_reactivate_TimeChanged_changes, Recreated_GuiChecks, Rewrite_FitPartialCharges, RotateToPrincipalAxisSystem_UndoRedo, SaturateAtoms_findBestMatching, SaturateAtoms_singleDegree, StoppableMakroAction, Subpackage_CodePatterns, Subpackage_JobMarket, Subpackage_LinearAlgebra, Subpackage_levmar, Subpackage_mpqc_open, Subpackage_vmg, Switchable_LogView, ThirdParty_MPQC_rebuilt_buildsystem, TrajectoryDependenant_MaxOrder, TremoloParser_IncreasedPrecision, TremoloParser_MultipleTimesteps, TremoloParser_setsAtomName, Ubuntu_1604_changes, stable
- Children:
- d067d45
- Parents:
- 178f92
- Location:
- src
- Files:
-
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
src/analyzer.cpp
r178f92 r437922 23 23 int main(int argc, char **argv) 24 24 { 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 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 output << scientific <<ShieldingPAS.Matrix[ ShieldingPAS.MatrixCounter ][j][k] << "\t"; //*(((k>1) && (k<6))? 1.e6 : 1.) << "\t";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 output << scientific <<Force.Matrix[ Force.MatrixCounter ][j][k] << "\t";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 if (!CreatePlotOrder(Time, KeySet, argv[3], "SimTime-Order", 1, "below", "y", "",1, 1, "bond order k", "Evaluation time [s]", Orderxrange.str().c_str(), "", "1" , "with linespoints", EnergyPlotLine)) return 1;308 309 310 if (!CreatePlotOrder(Energy, KeySet, argv[3], "DeltaEnergies-Order", 1, "outside", "y", "",1, 1, "bond order k", "absolute error in energy [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsEnergyPlotLine)) return 1;311 312 313 if (!CreatePlotOrder(Energy, KeySet, argv[3], "Energies-Order", 1, "outside", "", "",1, 1, "bond order k", "approximate energy [Ht]", Orderxrange.str().c_str(), "", "1" , "with linespoints", EnergyPlotLine)) return 1;314 315 316 317 318 if (!CreatePlotOrder(Force, KeySet, argv[3], "DeltaMinForces-Order", 2, "top right", "y", "",1, 1, "bond order k", "absolute error in min force [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;319 320 321 if (!CreatePlotOrder(Force, KeySet, argv[3], "DeltaMeanForces-Order", 2, "top right", "y", "",1, 1, "bond order k", "absolute error in mean force [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsFirstForceValuePlotLine)) return 1;322 323 324 if (!CreatePlotOrder(Force, KeySet, argv[3], "DeltaMaxForces-Order", 2, "top right", "y", "",1, 1, "bond order k", "absolute error in max force [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;325 326 327 328 CreatePlotHeader(output, "DeltaMinMeanMaxTotalForce-Order", 1, "bottom left", "y", NULL,1, 1, "bond order k", "absolute error in total forces [Ht/a.u.]");329 330 331 332 333 334 335 336 337 if (!CreatePlotOrder(Force, KeySet, argv[3], "MinForces-Order", 2, "bottom right", "y", "",1, 1, "bond order k", "absolute approximated min force [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;338 339 340 if (!CreatePlotOrder(Force, KeySet, argv[3], "MeanForces-Order", 2, "bottom right", "y", "",1, 1, "bond order k", "absolute approximated mean force [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", AbsFirstForceValuePlotLine)) return 1;341 342 343 if (!CreatePlotOrder(Force, KeySet, argv[3], "MaxForces-Order", 2, "bottom right", "y", "",1, 1, "bond order k", "absolute approximated max force [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 CreatePlotHeader(output, "ShieldingsPAS-Order", 1, "top right", NULL, NULL,1, 5, "nuclei index", "iso chemical shielding value [ppm]");393 CreatePlotHeader(output2, "DeltaShieldingsPAS-Order", 1, "top right", NULL, NULL,1, 5, "nuclei index", "iso chemical shielding value [ppm]");394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 25 periodentafel *periode = NULL; // and a period table of all elements 26 EnergyMatrix Energy; 27 EnergyMatrix Hcorrection; 28 ForceMatrix Force; 29 ForceMatrix Shielding; 30 ForceMatrix ShieldingPAS; 31 EnergyMatrix Time; 32 EnergyMatrix EnergyFragments; 33 EnergyMatrix HcorrectionFragments; 34 ForceMatrix ForceFragments; 35 ForceMatrix ShieldingFragments; 36 ForceMatrix ShieldingPASFragments; 37 KeySetsContainer KeySet; 38 ofstream output; 39 ofstream output2; 40 ofstream output3; 41 ofstream output4; 42 ifstream input; 43 stringstream filename; 44 time_t t = time(NULL); 45 struct tm *ts = localtime(&t); 46 char *datum = asctime(ts); 47 stringstream Orderxrange; 48 stringstream Fragmentxrange; 49 stringstream yrange; 50 char *dir = NULL; 51 bool Hcorrected = true; 52 int counter; 53 54 cout << "ANOVA Analyzer" << endl; 55 cout << "==============" << endl; 56 57 // Get the command line options 58 if (argc < 4) { 59 cout << "Usage: " << argv[0] << " <inputdir> <prefix> <outputdir> [elementsdb]" << endl; 60 cout << "<inputdir>\ttherein the output of a molecuilder fragmentation is expected, each fragment with a subdir containing an energy.all and a forces.all file." << endl; 61 cout << "<prefix>\tprefix of energy and forces file." << endl; 62 cout << "<outputdir>\tcreated plotfiles and datafiles are placed into this directory " << endl; 63 cout << "[elementsdb]\tpath to elements database, needed for shieldings." << endl; 64 return 1; 65 } else { 66 dir = (char *) Malloc(sizeof(char)*(strlen(argv[2])+2), "main: *dir"); 67 strcpy(dir, "/"); 68 strcat(dir, argv[2]); 69 } 70 71 if (argc > 4) { 72 cout << "Loading periodentafel." << endl; 73 periode = new periodentafel; 74 periode->LoadPeriodentafel(argv[4]); 75 } 76 77 // Test the given directory 78 if (!TestParams(argc, argv)) 79 return 1; 80 81 // +++++++++++++++++ PARSING +++++++++++++++++++++++++++++++ 82 83 // ------------- Parse through all Fragment subdirs -------- 84 if (!Energy.ParseFragmentMatrix(argv[1], dir, EnergySuffix,0,0)) return 1; 85 Hcorrected = Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX,0,0); 86 if (!Force.ParseFragmentMatrix(argv[1], dir, ForcesSuffix,0,0)) return 1; 87 if (!Time.ParseFragmentMatrix(argv[1], dir, TimeSuffix, 10,1)) return 1; 88 if (periode != NULL) { // also look for PAS values 89 if (!Shielding.ParseFragmentMatrix(argv[1], dir, ShieldingSuffix, 1, 0)) return 1; 90 if (!ShieldingPAS.ParseFragmentMatrix(argv[1], dir, ShieldingPASSuffix, 1, 0)) return 1; 91 } 92 93 // ---------- Parse the TE Factors into an array ----------------- 94 if (!Energy.ParseIndices()) return 1; 95 if (Hcorrected) Hcorrection.ParseIndices(); 96 97 // ---------- Parse the Force indices into an array --------------- 98 if (!Force.ParseIndices(argv[1])) return 1; 99 if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return 1; 100 if (!ForceFragments.ParseIndices(argv[1])) return 1; 101 102 // ---------- Parse the shielding indices into an array --------------- 103 if (periode != NULL) { // also look for PAS values 104 if(!Shielding.ParseIndices(argv[1])) return 1; 105 if(!ShieldingPAS.ParseIndices(argv[1])) return 1; 106 if (!ShieldingFragments.AllocateMatrix(Shielding.Header, Shielding.MatrixCounter, Shielding.RowCounter, Shielding.ColumnCounter)) return 1; 107 if (!ShieldingPASFragments.AllocateMatrix(ShieldingPAS.Header, ShieldingPAS.MatrixCounter, ShieldingPAS.RowCounter, ShieldingPAS.ColumnCounter)) return 1; 108 if(!ShieldingFragments.ParseIndices(argv[1])) return 1; 109 if(!ShieldingPASFragments.ParseIndices(argv[1])) return 1; 110 } 111 112 // ---------- Parse the KeySets into an array --------------- 113 if (!KeySet.ParseKeySets(argv[1], Force.RowCounter, Force.MatrixCounter)) return 1; 114 if (!KeySet.ParseManyBodyTerms()) return 1; 115 116 // ---------- Parse fragment files created by 'joiner' into an array ------------- 117 if (!EnergyFragments.ParseFragmentMatrix(argv[1], dir, EnergyFragmentSuffix,0,0)) return 1; 118 if (Hcorrected) HcorrectionFragments.ParseFragmentMatrix(argv[1], dir, HcorrectionFragmentSuffix,0,0); 119 if (!ForceFragments.ParseFragmentMatrix(argv[1], dir, ForceFragmentSuffix,0,0)) return 1; 120 if (periode != NULL) { // also look for PAS values 121 if (!ShieldingFragments.ParseFragmentMatrix(argv[1], dir, ShieldingFragmentSuffix, 1, 0)) return 1; 122 if (!ShieldingPASFragments.ParseFragmentMatrix(argv[1], dir, ShieldingPASFragmentSuffix, 1, 0)) return 1; 123 } 124 125 // +++++++++++++++ TESTING ++++++++++++++++++++++++++++++ 126 127 // print energy and forces to file 128 filename.str(""); 129 filename << argv[3] << "/" << "energy-forces.all"; 130 output.open(filename.str().c_str(), ios::out); 131 output << endl << "Total Energy" << endl << "==============" << endl << Energy.Header << endl; 132 for(int j=0;j<Energy.RowCounter[Energy.MatrixCounter];j++) { 133 for(int k=0;k<Energy.ColumnCounter;k++) 134 output << scientific << Energy.Matrix[ Energy.MatrixCounter ][j][k] << "\t"; 135 output << endl; 136 } 137 output << endl; 138 139 output << endl << "Total Forces" << endl << "===============" << endl << Force.Header << endl; 140 for(int j=0;j<Force.RowCounter[Force.MatrixCounter];j++) { 141 for(int k=0;k<Force.ColumnCounter;k++) 142 output << scientific << Force.Matrix[ Force.MatrixCounter ][j][k] << "\t"; 143 output << endl; 144 } 145 output << endl; 146 147 if (periode != NULL) { // also look for PAS values 148 output << endl << "Total Shieldings" << endl << "===============" << endl << Shielding.Header << endl; 149 for(int j=0;j<Shielding.RowCounter[Shielding.MatrixCounter];j++) { 150 for(int k=0;k<Shielding.ColumnCounter;k++) 151 output << scientific << Shielding.Matrix[ Shielding.MatrixCounter ][j][k] << "\t"; 152 output << endl; 153 } 154 output << endl; 155 156 output << endl << "Total Shieldings PAS" << endl << "===============" << endl << ShieldingPAS.Header << endl; 157 for(int j=0;j<ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter];j++) { 158 for(int k=0;k<ShieldingPAS.ColumnCounter;k++) 159 output << scientific << ShieldingPAS.Matrix[ ShieldingPAS.MatrixCounter ][j][k] << "\t"; 160 output << endl; 161 } 162 output << endl; 163 } 164 165 output << endl << "Total Times" << endl << "===============" << endl << Time.Header << endl; 166 for(int j=0;j<Time.RowCounter[Time.MatrixCounter];j++) { 167 for(int k=0;k<Time.ColumnCounter;k++) { 168 output << scientific << Time.Matrix[ Time.MatrixCounter ][j][k] << "\t"; 169 } 170 output << endl; 171 } 172 output << endl; 173 output.close(); 174 for(int k=0;k<Time.ColumnCounter;k++) 175 Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k] = Time.Matrix[ Time.MatrixCounter ][Time.RowCounter[Time.MatrixCounter]-1][k]; 176 177 // +++++++++++++++ ANALYZING ++++++++++++++++++++++++++++++ 178 179 cout << "Analyzing ..." << endl; 180 181 // ======================================= Creating the data files ============================================================== 182 183 // +++++++++++++++++++++++++++++++++++++++ Plotting Simtime vs Bond Order 184 // +++++++++++++++++++++++++++++++++++++++ Plotting Delta Simtime vs Bond Order 185 if (!OpenOutputFile(output, argv[3], "SimTime-Order.dat" )) return false; 186 if (!OpenOutputFile(output2, argv[3], "DeltaSimTime-Order.dat" )) return false; 187 for(int j=Time.RowCounter[Time.MatrixCounter];j--;) 188 for(int k=Time.ColumnCounter;k--;) { 189 Time.Matrix[ Time.MatrixCounter ][j][k] = 0.; 190 } 191 counter = 0; 192 output << "#Order\tFrag.No.\t" << Time.Header << endl; 193 output2 << "#Order\tFrag.No.\t" << Time.Header << endl; 194 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 195 for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) 196 for(int j=Time.RowCounter[Time.MatrixCounter];j--;) 197 for(int k=Time.ColumnCounter;k--;) { 198 Time.Matrix[ Time.MatrixCounter ][j][k] += Time.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 199 } 200 counter += KeySet.FragmentsPerOrder[BondOrder]; 201 output << BondOrder+1 << "\t" << counter; 202 output2 << BondOrder+1 << "\t" << counter; 203 for(int k=0;k<Time.ColumnCounter;k++) { 204 output << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k]; 205 if (fabs(Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k]) > MYEPSILON) 206 output2 << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k] / Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k]; 207 else 208 output2 << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k]; 209 } 210 output << endl; 211 output2 << endl; 212 } 213 output.close(); 214 output2.close(); 215 216 // +++++++++++++++++++++++++++++++++++++++ Plotting shieldings 217 218 if (periode != NULL) { // also look for PAS values 219 if (!CreateDataDeltaForcesOrderPerAtom(ShieldingPAS, ShieldingPASFragments, KeySet, argv[3], "DeltaShieldingsPAS-Order", "Plot of error between approximated shieldings and full shieldings versus the Bond Order", datum)) return 1; 220 if (!CreateDataForcesOrderPerAtom(ShieldingPASFragments, KeySet, argv[3], "ShieldingsPAS-Order", "Plot of approximated shieldings versus the Bond Order", datum)) return 1; 221 if (!AppendOutputFile(output, argv[3], "ShieldingsPAS-Order.dat" )) return false; 222 output << endl << "# Full" << endl; 223 for(int j=0;j<ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter];j++) { 224 output << j << "\t"; 225 for(int k=0;k<ShieldingPAS.ColumnCounter;k++) 226 output << scientific << ShieldingPAS.Matrix[ ShieldingPAS.MatrixCounter ][j][k] << "\t"; //*(((k>1) && (k<6))? 1.e6 : 1.) << "\t"; 227 output << endl; 228 } 229 } 230 output.close(); 231 232 233 // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in energy to full QM 234 if (!CreateDataDeltaEnergyOrder(Energy, EnergyFragments, KeySet, argv[3], "DeltaEnergies-Order", "Plot of error between approximated and full energies energies versus the Bond Order", datum)) return 1; 235 236 // +++++++++++++++++++++++++++++++++++Plotting Energies vs. Order 237 if (!CreateDataEnergyOrder(EnergyFragments, KeySet, argv[3], "Energies-Order", "Plot of approximated energies versus the Bond Order", datum)) return 1; 238 239 // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in forces to full QM 240 if (!CreateDataDeltaForcesOrderPerAtom(Force, ForceFragments, KeySet, argv[3], "DeltaForces-Order", "Plot of error between approximated forces and full forces versus the Bond Order", datum)) return 1; 241 242 // min force 243 if (!CreateDataDeltaForcesOrder(Force, ForceFragments, KeySet, argv[3], "DeltaMinForces-Order", "Plot of min error between approximated forces and full forces versus the Bond Order", datum, CreateMinimumForce)) return 1; 244 245 // mean force 246 if (!CreateDataDeltaForcesOrder(Force, ForceFragments, KeySet, argv[3], "DeltaMeanForces-Order", "Plot of mean error between approximated forces and full forces versus the Bond Order", datum, CreateMeanForce)) return 1; 247 248 // max force 249 if (!CreateDataDeltaForcesOrder(Force, ForceFragments, KeySet, argv[3], "DeltaMaxForces-Order", "Plot of max error between approximated forces and full forces versus the Bond Order", datum, CreateMaximumForce)) return 1; 250 251 // ++++++++++++++++++++++++++++++++++++++Plotting Forces vs. Order 252 if (!CreateDataForcesOrderPerAtom(ForceFragments, KeySet, argv[3], "Forces-Order", "Plot of approximated forces versus the Bond Order", datum)) return 1; 253 if (!AppendOutputFile(output, argv[3], "Forces-Order.dat" )) return false; 254 output << endl << "# Full" << endl; 255 for(int j=0;j<Force.RowCounter[Force.MatrixCounter];j++) { 256 output << j << "\t"; 257 for(int k=0;k<Force.ColumnCounter;k++) 258 output << scientific << Force.Matrix[ Force.MatrixCounter ][j][k] << "\t"; 259 output << endl; 260 } 261 output.close(); 262 // min force 263 if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MinForces-Order", "Plot of min approximated forces versus the Bond Order", datum, CreateMinimumForce)) return 1; 264 265 // mean force 266 if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MeanForces-Order", "Plot of mean approximated forces versus the Bond Order", datum, CreateMeanForce)) return 1; 267 268 // max force 269 if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MaxForces-Order", "Plot of max approximated forces versus the Bond Order", datum, CreateMaximumForce)) return 1; 270 271 // ++++++++++++++++++++++++++++++++++++++Plotting vector sum (should be 0) vs. bond order 272 if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "VectorSum-Order", "Plot of vector sum of the approximated forces versus the Bond Order", datum, CreateVectorSumForce)) return 1; 273 274 // +++++++++++++++++++++++++++++++Plotting energyfragments vs. order 275 if (!CreateDataFragment(EnergyFragments, KeySet, argv[3], "Energies-Fragment", "Plot of fragment energy versus the Fragment No", datum, CreateEnergy)) return 1; 276 if (!CreateDataFragment(EnergyFragments, KeySet, argv[3], "Energies-FragmentOrder", "Plot of fragment energy of each Fragment No vs. Bond Order", datum, CreateEnergy)) return 1; 277 if (!CreateDataFragmentOrder(EnergyFragments, KeySet, argv[3], "MaxEnergies-FragmentOrder", "Plot of maximum of fragment energy vs. Bond Order", datum, CreateMaxFragmentOrder)) return 1; 278 if (!CreateDataFragmentOrder(EnergyFragments, KeySet, argv[3], "MinEnergies-FragmentOrder", "Plot of minimum of fragment energy vs. Bond Order", datum, CreateMinFragmentOrder)) return 1; 279 280 // +++++++++++++++++++++++++++++++Ploting min/mean/max forces for each fragment 281 // min force 282 if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MinForces-Fragment", "Plot of min approximated forces versus the Fragment No", datum, CreateMinimumForce)) return 1; 283 284 // mean force 285 if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MeanForces-Fragment", "Plot of mean approximated forces versus the Fragment No", datum, CreateMeanForce)) return 1; 286 287 // max force 288 if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MaxForces-Fragment", "Plot of max approximated forces versus the Fragment No", datum, CreateMaximumForce)) return 1; 289 290 // +++++++++++++++++++++++++++++++Ploting min/mean/max forces for each fragment per order 291 // min force 292 if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MinForces-FragmentOrder", "Plot of min approximated forces of each Fragment No vs. Bond Order", datum, CreateMinimumForce)) return 1; 293 294 // mean force 295 if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MeanForces-FragmentOrder", "Plot of mean approximated forces of each Fragment No vs. Bond Order", datum, CreateMeanForce)) return 1; 296 297 // max force 298 if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MaxForces-FragmentOrder", "Plot of max approximated forces of each Fragment No vs. Bond Order", datum, CreateMaximumForce)) return 1; 299 300 // ======================================= Creating the plot files ============================================================== 301 302 Orderxrange << "[1:" << KeySet.Order << "]"; 303 Fragmentxrange << "[0:" << KeySet.FragmentCounter+1 << "]"; 304 yrange.str("[1e-8:1e+1]"); 305 306 // +++++++++++++++++++++++++++++++++++++++ Plotting Simtime vs Bond Order 307 if (!CreatePlotOrder(Time, KeySet, argv[3], "SimTime-Order", 1, "below", "y", "", 1, 1, "bond order k", "Evaluation time [s]", Orderxrange.str().c_str(), "", "1" , "with linespoints", EnergyPlotLine)) return 1; 308 309 // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in energy to full QM 310 if (!CreatePlotOrder(Energy, KeySet, argv[3], "DeltaEnergies-Order", 1, "outside", "y", "", 1, 1, "bond order k", "absolute error in energy [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsEnergyPlotLine)) return 1; 311 312 // +++++++++++++++++++++++++++++++++++Plotting Energies vs. Order 313 if (!CreatePlotOrder(Energy, KeySet, argv[3], "Energies-Order", 1, "outside", "", "", 1, 1, "bond order k", "approximate energy [Ht]", Orderxrange.str().c_str(), "", "1" , "with linespoints", EnergyPlotLine)) return 1; 314 315 // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in forces to full QM 316 yrange.str("[1e-8:1e+0]"); 317 // min force 318 if (!CreatePlotOrder(Force, KeySet, argv[3], "DeltaMinForces-Order", 2, "top right", "y", "", 1, 1, "bond order k", "absolute error in min force [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", ForceMagnitudePlotLine)) return 1; 319 320 // mean force 321 if (!CreatePlotOrder(Force, KeySet, argv[3], "DeltaMeanForces-Order", 2, "top right", "y", "", 1, 1, "bond order k", "absolute error in mean force [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsFirstForceValuePlotLine)) return 1; 322 323 // max force 324 if (!CreatePlotOrder(Force, KeySet, argv[3], "DeltaMaxForces-Order", 2, "top right", "y", "", 1, 1, "bond order k", "absolute error in max force [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", ForceMagnitudePlotLine)) return 1; 325 326 // min/mean/max comparison for total force 327 if(!OpenOutputFile(output, argv[3], "DeltaMinMeanMaxTotalForce-Order.pyx")) return 1; 328 CreatePlotHeader(output, "DeltaMinMeanMaxTotalForce-Order", 1, "bottom left", "y", NULL, 1, 1, "bond order k", "absolute error in total forces [Ht/a.u.]"); 329 output << "plot " << Orderxrange.str().c_str() << " [1e-8:1e+0] \\" << endl; 330 output << "'DeltaMinForces-Order.dat' title 'minimum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints, \\" << endl; 331 output << "'DeltaMeanForces-Order.dat' title 'mean' using 1:(abs($" << 8 << ")) with linespoints, \\" << endl; 332 output << "'DeltaMaxForces-Order.dat' title 'maximum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints" << endl; 333 output.close(); 334 335 // ++++++++++++++++++++++++++++++++++++++Plotting Forces vs. Order 336 // min force 337 if (!CreatePlotOrder(Force, KeySet, argv[3], "MinForces-Order", 2, "bottom right", "y", "", 1, 1, "bond order k", "absolute approximated min force [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", ForceMagnitudePlotLine)) return 1; 338 339 // mean force 340 if (!CreatePlotOrder(Force, KeySet, argv[3], "MeanForces-Order", 2, "bottom right", "y", "", 1, 1, "bond order k", "absolute approximated mean force [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", AbsFirstForceValuePlotLine)) return 1; 341 342 // max force 343 if (!CreatePlotOrder(Force, KeySet, argv[3], "MaxForces-Order", 2, "bottom right", "y", "", 1, 1, "bond order k", "absolute approximated max force [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", ForceMagnitudePlotLine)) return 1; 344 345 // min/mean/max comparison for total force 346 if(!OpenOutputFile(output, argv[3],"MinMeanMaxTotalForce-Order.pyx")) return 1; 347 CreatePlotHeader(output, "MinMeanMaxTotalForce-Order", 1, "bottom left", "y", NULL, 1, 1, "bond order k", "absolute total force [Ht/a.u.]"); 348 output << "plot "<< Orderxrange.str().c_str() << " [1e-8:1e+0] \\" << endl; 349 output << "'MinForces-Order.dat' title 'minimum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints, \\" << endl; 350 output << "'MeanForces-Order.dat' title 'mean' using 1:(abs($" << 8 << ")) with linespoints, \\" << endl; 351 output << "'MaxForces-Order.dat' title 'maximum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints" << endl; 352 output.close(); 353 354 // ++++++++++++++++++++++++++++++++++++++Plotting vector sum vs. Order 355 356 if (!CreatePlotOrder(Force, KeySet, argv[3], "VectorSum-Order", 2, "bottom right", "y" ,"", 1, 1, "bond order k", "vector sum of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", ForceMagnitudePlotLine)) return 1; 357 358 // +++++++++++++++++++++++++++++++Plotting energyfragments vs. order 359 yrange.str(""); 360 yrange << "[" << EnergyFragments.FindMinValue() << ":" << EnergyFragments.FindMaxValue() << "]"; 361 if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "Energies-Fragment", 5, "below", "y", "", 1, 5, "fragment number", "Energies of each fragment [Ht]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with points", AbsEnergyPlotLine)) return 1; 362 if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "Energies-FragmentOrder", 5, "below", "y", "", 1, 1, "bond order", "Energies of each fragment [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with points", AbsEnergyPlotLine)) return 1; 363 if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "MaxEnergies-FragmentOrder", 5, "below", "y", "", 1, 1, "bond order", "Maximum fragment energy [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsEnergyPlotLine)) return 1; 364 if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "MinEnergies-FragmentOrder", 5, "below", "y", "", 1, 1, "bond order", "Minimum fragment energy [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsEnergyPlotLine)) return 1; 365 366 // +++++++++++++++++++++++++++++++=Ploting min/mean/max forces for each fragment 367 yrange.str(""); 368 yrange << "[" << ForceFragments.FindMinValue() << ":" << ForceFragments.FindMaxValue()<< "]"; 369 // min 370 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MinForces-Fragment", 5, "below", "y", "set boxwidth 0.2", 1, 5, "fragment number", "minimum of approximated forces [Ht/a.u.]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with boxes fillcolor", BoxesForcePlotLine)) return 1; 371 372 // mean 373 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MeanForces-Fragment", 5, "below", "y", "set boxwidth 0.2", 1, 5, "fragment number", "mean of approximated forces [Ht/a.u.]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with boxes fillcolor", BoxesFirstForceValuePlotLine)) return 1; 374 375 // max 376 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MaxForces-Fragment", 5, "below", "y", "set boxwidth 0.2", 1, 5, "fragment number", "maximum of approximated forces [Ht/a.u.]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with boxes fillcolor", BoxesForcePlotLine)) return 1; 377 378 // +++++++++++++++++++++++++++++++=Ploting min/mean/max forces for each fragment per bond order 379 // min 380 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MinForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "minimum of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesForcePlotLine)) return 1; 381 382 // mean 383 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MeanForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "mean of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesFirstForceValuePlotLine)) return 1; 384 385 // max 386 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MaxForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "maximum of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesForcePlotLine)) return 1; 387 388 // +++++++++++++++++++++++++++++++=Ploting approximated and true shielding for each atom 389 if (periode != NULL) { // also look for PAS values 390 if(!OpenOutputFile(output, argv[3], "ShieldingsPAS-Order.pyx")) return 1; 391 if(!OpenOutputFile(output2, argv[3], "DeltaShieldingsPAS-Order.pyx")) return 1; 392 CreatePlotHeader(output, "ShieldingsPAS-Order", 1, "top right", NULL, NULL, 1, 5, "nuclei index", "iso chemical shielding value [ppm]"); 393 CreatePlotHeader(output2, "DeltaShieldingsPAS-Order", 1, "top right", NULL, NULL, 1, 5, "nuclei index", "iso chemical shielding value [ppm]"); 394 double step=0.8/KeySet.Order; 395 output << "set boxwidth " << step << endl; 396 output << "plot [0:" << ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter]+10 << "]\\" << endl; 397 output2 << "plot [0:" << ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter]+10 << "]\\" << endl; 398 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 399 output << "'ShieldingsPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1+" << step*(double)BondOrder << "):7 with boxes, \\" << endl; 400 output2 << "'DeltaShieldingsPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1):7 with linespoints"; 401 if (BondOrder-1 != KeySet.Order) 402 output2 << ", \\" << endl; 403 } 404 output << "'ShieldingsPAS-Order.dat' index " << KeySet.Order << " title 'Full' using ($1+" << step*(double)KeySet.Order << "):7 with boxes" << endl; 405 output.close(); 406 output2.close(); 407 } 408 409 // create Makefile 410 if(!OpenOutputFile(output, argv[3], "Makefile")) return 1; 411 output << "PYX = $(shell ls *.pyx)" << endl << endl; 412 output << "EPS = $(PYX:.pyx=.eps)" << endl << endl; 413 output << "%.eps: %.pyx" << endl; 414 output << "\t~/build/pyxplot/pyxplot $<" << endl << endl; 415 output << "all: $(EPS)" << endl << endl; 416 output << ".PHONY: clean" << endl; 417 output << "clean:" << endl; 418 output << "\trm -rf $(EPS)" << endl; 419 output.close(); 420 421 // ++++++++++++++++ exit ++++++++++++++++++++++++++++++++++ 422 delete(periode); 423 Free((void **)&dir, "main: *dir"); 424 cout << "done." << endl; 425 return 0; 426 426 }; 427 427 -
src/atom.cpp
r178f92 r437922 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 91 ostream & operator << (ostream &ost, 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
r178f92 r437922 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 84 ostream & operator << (ostream &ost, 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 97 98 99 100 96 if(leftatom == Atom) 97 return rightatom; 98 if(rightatom == Atom) 99 return leftatom; 100 return NULL; 101 101 }; 102 102 … … 107 107 bond * bond::GetFirstBond() 108 108 { 109 109 return GetFirst(this); 110 110 }; 111 111 … … 116 116 bond * bond::GetLastBond() 117 117 { 118 118 return GetLast(this); 119 119 }; 120 120 … … 124 124 enum Shading bond::IsUsed() 125 125 { 126 126 return Used; 127 127 }; 128 128 … … 133 133 bool bond::Contains(const atom *ptr) 134 134 { 135 135 return ((leftatom == ptr) || (rightatom == ptr)); 136 136 }; 137 137 … … 142 142 bool bond::Contains(const int number) 143 143 { 144 144 return ((leftatom->nr == number) || (rightatom->nr == number)); 145 145 }; 146 146 … … 149 149 */ 150 150 bool bond::MarkUsed(enum Shading color) { 151 152 153 154 155 156 157 151 if (Used == black) { 152 cerr << "ERROR: Bond " << this << " was already marked black!." << endl; 153 return false; 154 } else { 155 Used = color; 156 return true; 157 } 158 158 }; 159 159 … … 162 162 */ 163 163 void bond::ResetUsed() { 164 164 Used = white; 165 165 }; -
src/boundary.cpp
r178f92 r437922 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 33 34 35 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 36 } 37 37 ; … … 39 39 void BoundaryPointSet::AddLine(class BoundaryLineSet *line) 40 40 { 41 42 43 44 45 46 47 48 49 50 51 41 cout << Verbose(6) << "Adding " << *this << " to line " << *line << "." 42 << endl; 43 if (line->endpoints[0] == this) 44 { 45 lines.insert(LinePair(line->endpoints[1]->Nr, line)); 46 } 47 else 48 { 49 lines.insert(LinePair(line->endpoints[0]->Nr, line)); 50 } 51 LinesCount++; 52 52 } 53 53 ; … … 56 56 operator <<(ostream &ost, BoundaryPointSet &a) 57 57 { 58 59 58 ost << "[" << a.Nr << "|" << a.node->Name << "]"; 59 return ost; 60 60 } 61 61 ; … … 65 65 BoundaryLineSet::BoundaryLineSet() 66 66 { 67 68 69 70 67 for (int i = 0; i < 2; i++) 68 endpoints[i] = NULL; 69 TrianglesCount = 0; 70 Nr = -1; 71 71 } 72 72 ; … … 74 74 BoundaryLineSet::BoundaryLineSet(class BoundaryPointSet *Point[2], int number) 75 75 { 76 77 78 79 80 81 82 83 84 85 76 // set number 77 Nr = number; 78 // set endpoints in ascending order 79 SetEndpointsOrdered(endpoints, Point[0], Point[1]); 80 // add this line to the hash maps of both endpoints 81 Point[0]->AddLine(this); //Taken out, to check whether we can avoid unwanted double adding. 82 Point[1]->AddLine(this); // 83 // clear triangles list 84 TrianglesCount = 0; 85 cout << Verbose(5) << "New Line with endpoints " << *this << "." << endl; 86 86 } 87 87 ; … … 89 89 BoundaryLineSet::~BoundaryLineSet() 90 90 { 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 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; 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 1015 1016 1017 1018 1019 1020 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 1022 } 1023 1023 ; … … 1031 1031 Tesselation::GuessStartingTriangle(ofstream *out) 1032 1032 { 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 1033 // 4b. create a starting triangle 1034 // 4b1. create all distances 1035 DistanceMultiMap DistanceMMap; 1036 double distance, tmp; 1037 Vector PlaneVector, TrialVector; 1038 PointMap::iterator A, B, C; // three nodes of the first triangle 1039 A = PointsOnBoundary.begin(); // the first may be chosen arbitrarily 1040 1041 // with A chosen, take each pair B,C and sort 1042 if (A != PointsOnBoundary.end()) 1043 { 1044 B = A; 1045 B++; 1046 for (; B != PointsOnBoundary.end(); B++) 1047 { 1048 C = B; 1049 C++; 1050 for (; C != PointsOnBoundary.end(); C++) 1051 { 1052 tmp = A->second->node->x.DistanceSquared(&B->second->node->x); 1053 distance = tmp * tmp; 1054 tmp = A->second->node->x.DistanceSquared(&C->second->node->x); 1055 distance += tmp * tmp; 1056 tmp = B->second->node->x.DistanceSquared(&C->second->node->x); 1057 distance += tmp * tmp; 1058 DistanceMMap.insert(DistanceMultiMapPair(distance, pair< 1059 PointMap::iterator, PointMap::iterator> (B, C))); 1060 } 1061 } 1062 } 1063 // // listing distances 1064 // *out << Verbose(1) << "Listing DistanceMMap:"; 1065 // for(DistanceMultiMap::iterator runner = DistanceMMap.begin(); runner != DistanceMMap.end(); runner++) { 1066 // *out << " " << runner->first << "(" << *runner->second.first->second << ", " << *runner->second.second->second << ")"; 1067 // } 1068 // *out << endl; 1069 // 4b2. pick three baselines forming a triangle 1070 // 1. we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate 1071 DistanceMultiMap::iterator baseline = DistanceMMap.begin(); 1072 for (; baseline != DistanceMMap.end(); baseline++) 1073 { 1074 // we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate 1075 // 2. next, we have to check whether all points reside on only one side of the triangle 1076 // 3. construct plane vector 1077 PlaneVector.MakeNormalVector(&A->second->node->x, 1078 &baseline->second.first->second->node->x, 1079 &baseline->second.second->second->node->x); 1080 *out << Verbose(2) << "Plane vector of candidate triangle is "; 1081 PlaneVector.Output(out); 1082 *out << endl; 1083 // 4. loop over all points 1084 double sign = 0.; 1085 PointMap::iterator checker = PointsOnBoundary.begin(); 1086 for (; checker != PointsOnBoundary.end(); checker++) 1087 { 1088 // (neglecting A,B,C) 1089 if ((checker == A) || (checker == baseline->second.first) || (checker 1090 == baseline->second.second)) 1091 continue; 1092 // 4a. project onto plane vector 1093 TrialVector.CopyVector(&checker->second->node->x); 1094 TrialVector.SubtractVector(&A->second->node->x); 1095 distance = TrialVector.Projection(&PlaneVector); 1096 if (fabs(distance) < 1e-4) // we need to have a small epsilon around 0 which is still ok 1097 continue; 1098 *out << Verbose(3) << "Projection of " << checker->second->node->Name 1099 << " yields distance of " << distance << "." << endl; 1100 tmp = distance / fabs(distance); 1101 // 4b. Any have different sign to than before? (i.e. would lie outside convex hull with this starting triangle) 1102 if ((sign != 0) && (tmp != sign)) 1103 { 1104 // 4c. If so, break 4. loop and continue with next candidate in 1. loop 1105 *out << Verbose(2) << "Current candidates: " 1106 << A->second->node->Name << "," 1107 << baseline->second.first->second->node->Name << "," 1108 << baseline->second.second->second->node->Name << " leave " 1109 << checker->second->node->Name << " outside the convex hull." 1110 << endl; 1111 break; 1112 } 1113 else 1114 { // note the sign for later 1115 *out << Verbose(2) << "Current candidates: " 1116 << A->second->node->Name << "," 1117 << baseline->second.first->second->node->Name << "," 1118 << baseline->second.second->second->node->Name << " leave " 1119 << checker->second->node->Name << " inside the convex hull." 1120 << endl; 1121 sign = tmp; 1122 } 1123 // 4d. Check whether the point is inside the triangle (check distance to each node 1124 tmp = checker->second->node->x.DistanceSquared(&A->second->node->x); 1125 int innerpoint = 0; 1126 if ((tmp < A->second->node->x.DistanceSquared( 1127 &baseline->second.first->second->node->x)) && (tmp 1128 < A->second->node->x.DistanceSquared( 1129 &baseline->second.second->second->node->x))) 1130 innerpoint++; 1131 tmp = checker->second->node->x.DistanceSquared( 1132 &baseline->second.first->second->node->x); 1133 if ((tmp < baseline->second.first->second->node->x.DistanceSquared( 1134 &A->second->node->x)) && (tmp 1135 < baseline->second.first->second->node->x.DistanceSquared( 1136 &baseline->second.second->second->node->x))) 1137 innerpoint++; 1138 tmp = checker->second->node->x.DistanceSquared( 1139 &baseline->second.second->second->node->x); 1140 if ((tmp < baseline->second.second->second->node->x.DistanceSquared( 1141 &baseline->second.first->second->node->x)) && (tmp 1142 < baseline->second.second->second->node->x.DistanceSquared( 1143 &A->second->node->x))) 1144 innerpoint++; 1145 // 4e. If so, break 4. loop and continue with next candidate in 1. loop 1146 if (innerpoint == 3) 1147 break; 1148 } 1149 // 5. come this far, all on same side? Then break 1. loop and construct triangle 1150 if (checker == PointsOnBoundary.end()) 1151 { 1152 *out << "Looks like we have a candidate!" << endl; 1153 break; 1154 } 1155 } 1156 if (baseline != DistanceMMap.end()) 1157 { 1158 BPS[0] = baseline->second.first->second; 1159 BPS[1] = baseline->second.second->second; 1160 BLS[0] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 1161 BPS[0] = A->second; 1162 BPS[1] = baseline->second.second->second; 1163 BLS[1] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 1164 BPS[0] = baseline->second.first->second; 1165 BPS[1] = A->second; 1166 BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 1167 1168 // 4b3. insert created triangle 1169 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 1170 TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS)); 1171 TrianglesOnBoundaryCount++; 1172 for (int i = 0; i < NDIM; i++) 1173 { 1174 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BTS->lines[i])); 1175 LinesOnBoundaryCount++; 1176 } 1177 1178 *out << Verbose(1) << "Starting triangle is " << *BTS << "." << endl; 1179 } 1180 else 1181 { 1182 *out << Verbose(1) << "No starting triangle found." << endl; 1183 exit(255); 1184 } 1185 1185 } 1186 1186 ; … … 1191 1191 * -# if the lines contains to only one triangle 1192 1192 * -# We search all points in the boundary 1193 * 1194 * 1195 * 1196 * 1193 * -# if the triangle with the baseline and the current point has the smallest of angles (comparison between normal vectors 1194 * -# if the triangle is in forward direction of the baseline (at most 90 degrees angle between vector orthogonal to 1195 * baseline in triangle plane pointing out of the triangle and normal vector of new triangle) 1196 * -# then we have a new triangle, whose baselines we again add (or increase their TriangleCount) 1197 1197 * \param *out output stream for debugging 1198 1198 * \param *configuration for IsAngstroem … … 1201 1201 void 1202 1202 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 1203 molecule *mol) 1204 { 1205 bool flag; 1206 PointMap::iterator winner; 1207 class BoundaryPointSet *peak = NULL; 1208 double SmallestAngle, TempAngle; 1209 Vector NormalVector, VirtualNormalVector, CenterVector, TempVector, 1210 PropagationVector; 1211 LineMap::iterator LineChecker[2]; 1212 do 1213 { 1214 flag = false; 1215 for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline 1216 != LinesOnBoundary.end(); baseline++) 1217 if (baseline->second->TrianglesCount == 1) 1218 { 1219 *out << Verbose(2) << "Current baseline is between " 1220 << *(baseline->second) << "." << endl; 1221 // 5a. go through each boundary point if not _both_ edges between either endpoint of the current line and this point exist (and belong to 2 triangles) 1222 SmallestAngle = M_PI; 1223 BTS = baseline->second->triangles.begin()->second; // there is only one triangle so far 1224 // get peak point with respect to this base line's only triangle 1225 for (int i = 0; i < 3; i++) 1226 if ((BTS->endpoints[i] != baseline->second->endpoints[0]) 1227 && (BTS->endpoints[i] != baseline->second->endpoints[1])) 1228 peak = BTS->endpoints[i]; 1229 *out << Verbose(3) << " and has peak " << *peak << "." << endl; 1230 // normal vector of triangle 1231 BTS->GetNormalVector(NormalVector); 1232 *out << Verbose(4) << "NormalVector of base triangle is "; 1233 NormalVector.Output(out); 1234 *out << endl; 1235 // offset to center of triangle 1236 CenterVector.Zero(); 1237 for (int i = 0; i < 3; i++) 1238 CenterVector.AddVector(&BTS->endpoints[i]->node->x); 1239 CenterVector.Scale(1. / 3.); 1240 *out << Verbose(4) << "CenterVector of base triangle is "; 1241 CenterVector.Output(out); 1242 *out << endl; 1243 // vector in propagation direction (out of triangle) 1244 // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection) 1245 TempVector.CopyVector(&baseline->second->endpoints[0]->node->x); 1246 TempVector.SubtractVector(&baseline->second->endpoints[1]->node->x); 1247 PropagationVector.MakeNormalVector(&TempVector, &NormalVector); 1248 TempVector.CopyVector(&CenterVector); 1249 TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center! 1250 //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl; 1251 if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline 1252 PropagationVector.Scale(-1.); 1253 *out << Verbose(4) << "PropagationVector of base triangle is "; 1254 PropagationVector.Output(out); 1255 *out << endl; 1256 winner = PointsOnBoundary.end(); 1257 for (PointMap::iterator target = PointsOnBoundary.begin(); target 1258 != PointsOnBoundary.end(); target++) 1259 if ((target->second != baseline->second->endpoints[0]) 1260 && (target->second != baseline->second->endpoints[1])) 1261 { // don't take the same endpoints 1262 *out << Verbose(3) << "Target point is " << *(target->second) 1263 << ":"; 1264 bool continueflag = true; 1265 1266 VirtualNormalVector.CopyVector( 1267 &baseline->second->endpoints[0]->node->x); 1268 VirtualNormalVector.AddVector( 1269 &baseline->second->endpoints[0]->node->x); 1270 VirtualNormalVector.Scale(-1. / 2.); // points now to center of base line 1271 VirtualNormalVector.AddVector(&target->second->node->x); // points from center of base line to target 1272 TempAngle = VirtualNormalVector.Angle(&PropagationVector); 1273 continueflag = continueflag && (TempAngle < (M_PI/2.)); // no bends bigger than Pi/2 (90 degrees) 1274 if (!continueflag) 1275 { 1276 *out << Verbose(4) 1277 << "Angle between propagation direction and base line to " 1278 << *(target->second) << " is " << TempAngle 1279 << ", bad direction!" << endl; 1280 continue; 1281 } 1282 else 1283 *out << Verbose(4) 1284 << "Angle between propagation direction and base line to " 1285 << *(target->second) << " is " << TempAngle 1286 << ", good direction!" << endl; 1287 LineChecker[0] = baseline->second->endpoints[0]->lines.find( 1288 target->first); 1289 LineChecker[1] = baseline->second->endpoints[1]->lines.find( 1290 target->first); 1291 // if (LineChecker[0] != baseline->second->endpoints[0]->lines.end()) 1292 // *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl; 1293 // else 1294 // *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has no line to " << *(target->second) << " as endpoint." << endl; 1295 // if (LineChecker[1] != baseline->second->endpoints[1]->lines.end()) 1296 // *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl; 1297 // else 1298 // *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has no line to " << *(target->second) << " as endpoint." << endl; 1299 // check first endpoint (if any connecting line goes to target or at least not more than 1) 1300 continueflag = continueflag && (((LineChecker[0] 1301 == baseline->second->endpoints[0]->lines.end()) 1302 || (LineChecker[0]->second->TrianglesCount == 1))); 1303 if (!continueflag) 1304 { 1305 *out << Verbose(4) << *(baseline->second->endpoints[0]) 1306 << " has line " << *(LineChecker[0]->second) 1307 << " to " << *(target->second) 1308 << " as endpoint with " 1309 << LineChecker[0]->second->TrianglesCount 1310 << " triangles." << endl; 1311 continue; 1312 } 1313 // check second endpoint (if any connecting line goes to target or at least not more than 1) 1314 continueflag = continueflag && (((LineChecker[1] 1315 == baseline->second->endpoints[1]->lines.end()) 1316 || (LineChecker[1]->second->TrianglesCount == 1))); 1317 if (!continueflag) 1318 { 1319 *out << Verbose(4) << *(baseline->second->endpoints[1]) 1320 << " has line " << *(LineChecker[1]->second) 1321 << " to " << *(target->second) 1322 << " as endpoint with " 1323 << LineChecker[1]->second->TrianglesCount 1324 << " triangles." << endl; 1325 continue; 1326 } 1327 // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint) 1328 continueflag = continueflag && (!(((LineChecker[0] 1329 != baseline->second->endpoints[0]->lines.end()) 1330 && (LineChecker[1] 1331 != baseline->second->endpoints[1]->lines.end()) 1332 && (GetCommonEndpoint(LineChecker[0]->second, 1333 LineChecker[1]->second) == peak)))); 1334 if (!continueflag) 1335 { 1336 *out << Verbose(4) << "Current target is peak!" << endl; 1337 continue; 1338 } 1339 // in case NOT both were found 1340 if (continueflag) 1341 { // create virtually this triangle, get its normal vector, calculate angle 1342 flag = true; 1343 VirtualNormalVector.MakeNormalVector( 1344 &baseline->second->endpoints[0]->node->x, 1345 &baseline->second->endpoints[1]->node->x, 1346 &target->second->node->x); 1347 // make it always point inward 1348 if (baseline->second->endpoints[0]->node->x.Projection( 1349 &VirtualNormalVector) > 0) 1350 VirtualNormalVector.Scale(-1.); 1351 // calculate angle 1352 TempAngle = NormalVector.Angle(&VirtualNormalVector); 1353 *out << Verbose(4) << "NormalVector is "; 1354 VirtualNormalVector.Output(out); 1355 *out << " and the angle is " << TempAngle << "." << endl; 1356 if (SmallestAngle > TempAngle) 1357 { // set to new possible winner 1358 SmallestAngle = TempAngle; 1359 winner = target; 1360 } 1361 } 1362 } 1363 // 5b. The point of the above whose triangle has the greatest angle with the triangle the current line belongs to (it only belongs to one, remember!): New triangle 1364 if (winner != PointsOnBoundary.end()) 1365 { 1366 *out << Verbose(2) << "Winning target point is " 1367 << *(winner->second) << " with angle " << SmallestAngle 1368 << "." << endl; 1369 // create the lins of not yet present 1370 BLS[0] = baseline->second; 1371 // 5c. add lines to the line set if those were new (not yet part of a triangle), delete lines that belong to two triangles) 1372 LineChecker[0] = baseline->second->endpoints[0]->lines.find( 1373 winner->first); 1374 LineChecker[1] = baseline->second->endpoints[1]->lines.find( 1375 winner->first); 1376 if (LineChecker[0] 1377 == baseline->second->endpoints[0]->lines.end()) 1378 { // create 1379 BPS[0] = baseline->second->endpoints[0]; 1380 BPS[1] = winner->second; 1381 BLS[1] = new class BoundaryLineSet(BPS, 1382 LinesOnBoundaryCount); 1383 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, 1384 BLS[1])); 1385 LinesOnBoundaryCount++; 1386 } 1387 else 1388 BLS[1] = LineChecker[0]->second; 1389 if (LineChecker[1] 1390 == baseline->second->endpoints[1]->lines.end()) 1391 { // create 1392 BPS[0] = baseline->second->endpoints[1]; 1393 BPS[1] = winner->second; 1394 BLS[2] = new class BoundaryLineSet(BPS, 1395 LinesOnBoundaryCount); 1396 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, 1397 BLS[2])); 1398 LinesOnBoundaryCount++; 1399 } 1400 else 1401 BLS[2] = LineChecker[1]->second; 1402 BTS = new class BoundaryTriangleSet(BLS, 1403 TrianglesOnBoundaryCount); 1404 TrianglesOnBoundary.insert(TrianglePair( 1405 TrianglesOnBoundaryCount, BTS)); 1406 TrianglesOnBoundaryCount++; 1407 } 1408 else 1409 { 1410 *out << Verbose(1) 1411 << "I could not determine a winner for this baseline " 1412 << *(baseline->second) << "." << endl; 1413 } 1414 1415 // 5d. If the set of lines is not yet empty, go to 5. and continue 1416 } 1417 else 1418 *out << Verbose(2) << "Baseline candidate " << *(baseline->second) 1419 << " has a triangle count of " 1420 << baseline->second->TrianglesCount << "." << endl; 1421 } 1422 while (flag); 1423 1423 1424 1424 } … … 1431 1431 Tesselation::AddPoint(atom *Walker) 1432 1432 { 1433 1434 1435 1436 1437 1433 PointTestPair InsertUnique; 1434 BPS[0] = new class BoundaryPointSet(Walker); 1435 InsertUnique = PointsOnBoundary.insert(PointPair(Walker->nr, BPS[0])); 1436 if (InsertUnique.second) // if new point was not present before, increase counter 1437 PointsOnBoundaryCount++; 1438 1438 } 1439 1439 ; … … 1447 1447 Tesselation::AddTrianglePoint(atom* Candidate, int n) 1448 1448 { 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1449 PointTestPair InsertUnique; 1450 TPS[n] = new class BoundaryPointSet(Candidate); 1451 InsertUnique = PointsOnBoundary.insert(PointPair(Candidate->nr, TPS[n])); 1452 if (InsertUnique.second) // if new point was not present before, increase counter 1453 { 1454 PointsOnBoundaryCount++; 1455 } 1456 else 1457 { 1458 delete TPS[n]; 1459 cout << Verbose(2) << "Atom " << *((InsertUnique.first)->second->node) 1460 << " gibt's schon in der PointMap." << endl; 1461 TPS[n] = (InsertUnique.first)->second; 1462 } 1463 1463 } 1464 1464 ; … … 1473 1473 void 1474 1474 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 1475 class BoundaryPointSet *b, int n) 1476 { 1477 LineMap::iterator LineWalker; 1478 //cout << "Manually checking endpoints for line." << endl; 1479 if ((a->lines.find(b->node->nr)) != a->lines.end()) // ->first == b->node->nr) 1480 //If a line is there, how do I recognize that beyond a shadow of a doubt? 1481 { 1482 //cout << Verbose(2) << "Line exists already, retrieving it from LinesOnBoundarySet" << endl; 1483 1484 LineWalker = LinesOnBoundary.end(); 1485 LineWalker--; 1486 1487 while (LineWalker->second->endpoints[0]->node->nr != min(a->node->nr, 1488 b->node->nr) or LineWalker->second->endpoints[1]->node->nr != max( 1489 a->node->nr, b->node->nr)) 1490 { 1491 //cout << Verbose(1) << "Looking for line which already exists"<< endl; 1492 LineWalker--; 1493 } 1494 BPS[0] = LineWalker->second->endpoints[0]; 1495 BPS[1] = LineWalker->second->endpoints[1]; 1496 BLS[n] = LineWalker->second; 1497 1498 } 1499 else 1500 { 1501 cout << Verbose(2) 1502 << "Adding line which has not been used before between " 1503 << *(a->node) << " and " << *(b->node) << "." << endl; 1504 BPS[0] = a; 1505 BPS[1] = b; 1506 BLS[n] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 1507 1508 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BLS[n])); 1509 LinesOnBoundaryCount++; 1510 1511 } 1512 1512 } 1513 1513 ; … … 1520 1520 { 1521 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1522 cout << Verbose(1) << "Adding triangle to its lines" << endl; 1523 TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS)); 1524 TrianglesOnBoundaryCount++; 1525 1526 /* 1527 * this is apparently done when constructing triangle 1528 1529 for (i=0; i<3; i++) 1530 { 1531 BLS[i]->AddTriangle(BTS); 1532 } 1533 */ 1534 1534 } 1535 1535 ; … … 1537 1537 1538 1538 double det_get(gsl_matrix *A, int inPlace) { 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1539 /* 1540 inPlace = 1 => A is replaced with the LU decomposed copy. 1541 inPlace = 0 => A is retained, and a copy is used for LU. 1542 */ 1543 1544 double det; 1545 int signum; 1546 gsl_permutation *p = gsl_permutation_alloc(A->size1); 1547 gsl_matrix *tmpA; 1548 1549 if (inPlace) 1550 tmpA = A; 1551 else { 1552 gsl_matrix *tmpA = gsl_matrix_alloc(A->size1, A->size2); 1553 gsl_matrix_memcpy(tmpA , A); 1554 } 1555 1556 1557 gsl_linalg_LU_decomp(tmpA , p , &signum); 1558 det = gsl_linalg_LU_det(tmpA , signum); 1559 gsl_permutation_free(p); 1560 if (! inPlace) 1561 gsl_matrix_free(tmpA); 1562 1563 return det; 1564 1564 }; 1565 1565 1566 1566 void get_sphere(Vector *center, Vector &a, Vector &b, Vector &c, double RADIUS) 1567 1567 { 1568 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 center->x[0] =0.5 * m12/ m11;1603 1604 center->x[2] =0.5 * m14/ m11;1605 1606 1607 1608 1609 1568 gsl_matrix *A = gsl_matrix_calloc(3,3); 1569 double m11, m12, m13, m14; 1570 1571 for(int i=0;i<3;i++) { 1572 gsl_matrix_set(A, i, 0, a.x[i]); 1573 gsl_matrix_set(A, i, 1, b.x[i]); 1574 gsl_matrix_set(A, i, 2, c.x[i]); 1575 } 1576 m11 = det_get(A, 1); 1577 1578 for(int i=0;i<3;i++) { 1579 gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]); 1580 gsl_matrix_set(A, i, 1, b.x[i]); 1581 gsl_matrix_set(A, i, 2, c.x[i]); 1582 } 1583 m12 = det_get(A, 1); 1584 1585 for(int i=0;i<3;i++) { 1586 gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]); 1587 gsl_matrix_set(A, i, 1, a.x[i]); 1588 gsl_matrix_set(A, i, 2, c.x[i]); 1589 } 1590 m13 = det_get(A, 1); 1591 1592 for(int i=0;i<3;i++) { 1593 gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]); 1594 gsl_matrix_set(A, i, 1, a.x[i]); 1595 gsl_matrix_set(A, i, 2, b.x[i]); 1596 } 1597 m14 = det_get(A, 1); 1598 1599 if (fabs(m11) < MYEPSILON) 1600 cerr << "ERROR: three points are colinear." << endl; 1601 1602 center->x[0] = 0.5 * m12/ m11; 1603 center->x[1] = -0.5 * m13/ m11; 1604 center->x[2] = 0.5 * m14/ m11; 1605 1606 if (fabs(a.Distance(center) - RADIUS) > MYEPSILON) 1607 cerr << "ERROR: The given center is further way by " << fabs(a.Distance(center) - RADIUS) << " from a than RADIUS." << endl; 1608 1609 gsl_matrix_free(A); 1610 1610 }; 1611 1611 … … 1629 1629 */ 1630 1630 void Get_center_of_sphere(Vector* Center, Vector a, Vector b, Vector c, Vector *NewUmkreismittelpunkt, Vector* Direction, Vector* AlternativeDirection, 1631 1632 { 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1631 double HalfplaneIndicator, double AlternativeIndicator, double alpha, double beta, double gamma, double RADIUS, double Umkreisradius) 1632 { 1633 Vector TempNormal, helper; 1634 double Restradius; 1635 Vector OtherCenter; 1636 cout << Verbose(3) << "Begin of Get_center_of_sphere.\n"; 1637 Center->Zero(); 1638 helper.CopyVector(&a); 1639 helper.Scale(sin(2.*alpha)); 1640 Center->AddVector(&helper); 1641 helper.CopyVector(&b); 1642 helper.Scale(sin(2.*beta)); 1643 Center->AddVector(&helper); 1644 helper.CopyVector(&c); 1645 helper.Scale(sin(2.*gamma)); 1646 Center->AddVector(&helper); 1647 //*Center = a * sin(2.*alpha) + b * sin(2.*beta) + c * sin(2.*gamma) ; 1648 Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma))); 1649 NewUmkreismittelpunkt->CopyVector(Center); 1650 cout << Verbose(4) << "Center of new circumference is " << *NewUmkreismittelpunkt << ".\n"; 1651 // Here we calculated center of circumscribing circle, using barycentric coordinates 1652 cout << Verbose(4) << "Center of circumference is " << *Center << " in direction " << *Direction << ".\n"; 1653 1654 TempNormal.CopyVector(&a); 1655 TempNormal.SubtractVector(&b); 1656 helper.CopyVector(&a); 1657 helper.SubtractVector(&c); 1658 TempNormal.VectorProduct(&helper); 1659 if (fabs(HalfplaneIndicator) < MYEPSILON) 1660 { 1661 if ((TempNormal.ScalarProduct(AlternativeDirection) <0 and AlternativeIndicator >0) or (TempNormal.ScalarProduct(AlternativeDirection) >0 and AlternativeIndicator <0)) 1662 { 1663 TempNormal.Scale(-1); 1664 } 1665 } 1666 else 1667 { 1668 if (TempNormal.ScalarProduct(Direction)<0 && HalfplaneIndicator >0 || TempNormal.ScalarProduct(Direction)>0 && HalfplaneIndicator<0) 1669 { 1670 TempNormal.Scale(-1); 1671 } 1672 } 1673 1674 TempNormal.Normalize(); 1675 Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius); 1676 cout << Verbose(4) << "Height of center of circumference to center of sphere is " << Restradius << ".\n"; 1677 TempNormal.Scale(Restradius); 1678 cout << Verbose(4) << "Shift vector to sphere of circumference is " << TempNormal << ".\n"; 1679 1680 Center->AddVector(&TempNormal); 1681 cout << Verbose(0) << "Center of sphere of circumference is " << *Center << ".\n"; 1682 get_sphere(&OtherCenter, a, b, c, RADIUS); 1683 cout << Verbose(0) << "OtherCenter of sphere of circumference is " << OtherCenter << ".\n"; 1684 cout << Verbose(3) << "End of Get_center_of_sphere.\n"; 1685 1685 }; 1686 1686 1687 1687 /** This recursive function finds a third point, to form a triangle with two given ones. 1688 1688 * Two atoms are fixed, a candidate is supplied, additionally two vectors for direction distinction, a Storage area to \ 1689 * 1690 * 1691 * 1692 * 1693 * 1694 * 1689 * supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \ 1690 * upon which we operate. 1691 * If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \ 1692 * direction and angle into Storage. 1693 * We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \ 1694 * with all neighbours of the candidate. 1695 1695 * @param a first point 1696 1696 * @param b second point … … 1709 1709 */ 1710 1710 void Tesselation::Find_next_suitable_point_via_Angle_of_Sphere(atom* a, atom* b, atom* c, atom* Candidate, atom* Parent, 1711 1712 1713 { 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1711 int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint, 1712 atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol) 1713 { 1714 cout << Verbose(2) << "Begin of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n"; 1715 cout << Verbose(3) << "Candidate is "<< *Candidate << endl; 1716 cout << Verbose(4) << "Baseline vector is " << *Chord << "." << endl; 1717 cout << Verbose(4) << "ReferencePoint is " << ReferencePoint << "." << endl; 1718 cout << Verbose(4) << "Normal of base triangle is " << *OldNormal << "." << endl; 1719 cout << Verbose(4) << "Search direction is " << *direction1 << "." << endl; 1720 /* OldNormal is normal vector on the old triangle 1721 * direction1 is normal on the triangle line, from which we come, as well as on OldNormal. 1722 * Chord points from b to a!!! 1723 */ 1724 Vector dif_a; //Vector from a to candidate 1725 Vector dif_b; //Vector from b to candidate 1726 Vector AngleCheck; 1727 Vector TempNormal, Umkreismittelpunkt; 1728 Vector Mittelpunkt; 1729 1730 double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius; 1731 double BallAngle, AlternativeSign; 1732 atom *Walker; // variable atom point 1733 1734 Vector NewUmkreismittelpunkt; 1735 1736 if (a != Candidate and b != Candidate and c != Candidate) { 1737 cout << Verbose(3) << "We have a unique candidate!" << endl; 1738 dif_a.CopyVector(&(a->x)); 1739 dif_a.SubtractVector(&(Candidate->x)); 1740 dif_b.CopyVector(&(b->x)); 1741 dif_b.SubtractVector(&(Candidate->x)); 1742 AngleCheck.CopyVector(&(Candidate->x)); 1743 AngleCheck.SubtractVector(&(a->x)); 1744 AngleCheck.ProjectOntoPlane(Chord); 1745 1746 SideA = dif_b.Norm(); 1747 SideB = dif_a.Norm(); 1748 SideC = Chord->Norm(); 1749 //Chord->Scale(-1); 1750 1751 alpha = Chord->Angle(&dif_a); 1752 beta = M_PI - Chord->Angle(&dif_b); 1753 gamma = dif_a.Angle(&dif_b); 1754 1755 cout << Verbose(2) << "Base triangle has sides " << dif_a << ", " << dif_b << ", " << *Chord << " with angles " << alpha/M_PI*180. << ", " << beta/M_PI*180. << ", " << gamma/M_PI*180. << "." << endl; 1756 1757 if (fabs(M_PI - alpha - beta - gamma) > MYEPSILON) { 1758 cerr << Verbose(0) << "WARNING: sum of angles for base triangle " << (alpha + beta + gamma)/M_PI*180. << " != 180.\n"; 1759 cout << Verbose(1) << "Base triangle has sides " << dif_a << ", " << dif_b << ", " << *Chord << " with angles " << alpha/M_PI*180. << ", " << beta/M_PI*180. << ", " << gamma/M_PI*180. << "." << endl; 1760 } 1761 1762 if ((M_PI*179./180. > alpha) && (M_PI*179./180. > beta) && (M_PI*179./180. > gamma)) { 1763 Umkreisradius = SideA / 2.0 / sin(alpha); 1764 //cout << Umkreisradius << endl; 1765 //cout << SideB / 2.0 / sin(beta) << endl; 1766 //cout << SideC / 2.0 / sin(gamma) << endl; 1767 1768 if (Umkreisradius < RADIUS) { //Checking whether ball will at least rest on points. 1769 cout << Verbose(3) << "Circle of circumference would fit: " << Umkreisradius << " < " << RADIUS << "." << endl; 1770 cout << Verbose(2) << "Candidate is "<< *Candidate << endl; 1771 sign = AngleCheck.ScalarProduct(direction1); 1772 if (fabs(sign)<MYEPSILON) { 1773 if (AngleCheck.ScalarProduct(OldNormal)<0) { 1774 sign =0; 1775 AlternativeSign=1; 1776 } else { 1777 sign =0; 1778 AlternativeSign=-1; 1779 } 1780 } else { 1781 sign /= fabs(sign); 1782 } 1783 if (sign >= 0) { 1784 cout << Verbose(3) << "Candidate is in search direction: " << sign << "." << endl; 1785 Get_center_of_sphere(&Mittelpunkt, (a->x), (b->x), (Candidate->x), &NewUmkreismittelpunkt, OldNormal, direction1, sign, AlternativeSign, alpha, beta, gamma, RADIUS, Umkreisradius); 1786 Mittelpunkt.SubtractVector(&ReferencePoint); 1787 cout << Verbose(3) << "Reference vector to sphere's center is " << Mittelpunkt << "." << endl; 1788 BallAngle = Mittelpunkt.Angle(OldNormal); 1789 cout << Verbose(3) << "Angle between normal of base triangle and center of ball sphere is :" << BallAngle << "." << endl; 1790 1791 //cout << "direction1 is " << *direction1 << "." << endl; 1792 //cout << "Mittelpunkt is " << Mittelpunkt << "."<< endl; 1793 //cout << Verbose(3) << "BallAngle is " << BallAngle << " Sign is " << sign << endl; 1794 1795 NewUmkreismittelpunkt.SubtractVector(&ReferencePoint); 1796 1797 if ((Mittelpunkt.ScalarProduct(direction1) >=0) || (fabs(NewUmkreismittelpunkt.Norm()) < MYEPSILON)) { 1798 if (Storage[0]< -1.5) { // first Candidate at all 1799 if (1) {//if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) { 1800 cout << Verbose(2) << "First good candidate is " << *Candidate << " with "; 1801 Opt_Candidate = Candidate; 1802 Storage[0] = sign; 1803 Storage[1] = AlternativeSign; 1804 Storage[2] = BallAngle; 1805 cout << " angle " << Storage[2] << " and Up/Down " << Storage[0] << endl; 1806 } else 1807 cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl; 1808 } else { 1809 if ( Storage[2] > BallAngle) { 1810 if (1) { //if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) { 1811 cout << Verbose(2) << "Next better candidate is " << *Candidate << " with "; 1812 Opt_Candidate = Candidate; 1813 Storage[0] = sign; 1814 Storage[1] = AlternativeSign; 1815 Storage[2] = BallAngle; 1816 cout << " angle " << Storage[2] << " and Up/Down " << Storage[0] << endl; 1817 } else 1818 cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl; 1819 } else { 1820 if (DEBUG) { 1821 cout << Verbose(3) << *Candidate << " looses against better candidate " << *Opt_Candidate << "." << endl; 1822 } 1823 } 1824 } 1825 } else { 1826 if (DEBUG) { 1827 cout << Verbose(3) << *Candidate << " refused due to Up/Down sign which is " << sign << endl; 1828 } 1829 } 1830 } else { 1831 if (DEBUG) { 1832 cout << Verbose(3) << *Candidate << " is not in search direction." << endl; 1833 } 1834 } 1835 } else { 1836 if (DEBUG) { 1837 cout << Verbose(3) << *Candidate << " would have circumference of " << Umkreisradius << " bigger than ball's radius " << RADIUS << "." << endl; 1838 } 1839 } 1840 } else { 1841 if (DEBUG) { 1842 cout << Verbose(0) << "Triangle consisting of " << *Candidate << ", " << *a << " and " << *b << " has an angle >150!" << endl; 1843 } 1844 } 1845 } else { 1846 if (DEBUG) { 1847 cout << Verbose(3) << *Candidate << " is either " << *a << " or " << *b << "." << endl; 1848 } 1849 } 1850 1851 if (RecursionLevel < 5) { // Seven is the recursion level threshold. 1852 for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) { // go through all bond 1853 Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate); 1854 if (Walker == Parent) { // don't go back the same bond 1855 continue; 1856 } else { 1857 Find_next_suitable_point_via_Angle_of_Sphere(a, b, c, Walker, Candidate, RecursionLevel+1, Chord, direction1, OldNormal, ReferencePoint, Opt_Candidate, Storage, RADIUS, mol); //call function again 1858 } 1859 } 1860 } 1861 cout << Verbose(2) << "End of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n"; 1862 1862 } 1863 1863 ; … … 1872 1872 void GetCenterofCircumcircle(Vector *Center, Vector *a, Vector *b, Vector *c) 1873 1873 { 1874 1875 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 1874 Vector helper; 1875 double alpha, beta, gamma; 1876 Vector SideA, SideB, SideC; 1877 SideA.CopyVector(b); 1878 SideA.SubtractVector(c); 1879 SideB.CopyVector(c); 1880 SideB.SubtractVector(a); 1881 SideC.CopyVector(a); 1882 SideC.SubtractVector(b); 1883 alpha = M_PI - SideB.Angle(&SideC); 1884 beta = M_PI - SideC.Angle(&SideA); 1885 gamma = M_PI - SideA.Angle(&SideB); 1886 cout << Verbose(3) << "INFO: alpha = " << alpha/M_PI*180. << ", beta = " << beta/M_PI*180. << ", gamma = " << gamma/M_PI*180. << "." << endl; 1887 if (fabs(M_PI - alpha - beta - gamma) > HULLEPSILON) 1888 cerr << "Sum of angles " << (alpha+beta+gamma)/M_PI*180. << " > 180 degrees by " << fabs(M_PI - alpha - beta - gamma)/M_PI*180. << "!" << endl; 1889 1890 Center->Zero(); 1891 helper.CopyVector(a); 1892 helper.Scale(sin(2.*alpha)); 1893 Center->AddVector(&helper); 1894 helper.CopyVector(b); 1895 helper.Scale(sin(2.*beta)); 1896 Center->AddVector(&helper); 1897 helper.CopyVector(c); 1898 helper.Scale(sin(2.*gamma)); 1899 Center->AddVector(&helper); 1900 Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma))); 1901 1901 }; 1902 1902 … … 1916 1916 double GetPathLengthonCircumCircle(Vector &CircleCenter, Vector &CirclePlaneNormal, double CircleRadius, Vector &NewSphereCenter, Vector &OldSphereCenter, Vector &NormalVector, Vector &SearchDirection) 1917 1917 { 1918 1919 1920 1921 1922 1923 1924 cerr << "ERROR: Something's very wrong here: NewSphereCenter is not on the band's plane as desired by " <<fabs(helper.ScalarProduct(&CirclePlaneNormal))<< "!" << endl;1925 1926 1927 1928 1929 1930 1931 1932 1933 if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)// acos is not unique on [0, 2.*M_PI), hence extra check to decide between two half intervals1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1918 Vector helper; 1919 double radius, alpha; 1920 1921 helper.CopyVector(&NewSphereCenter); 1922 // test whether new center is on the parameter circle's plane 1923 if (fabs(helper.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) { 1924 cerr << "ERROR: Something's very wrong here: NewSphereCenter is not on the band's plane as desired by " <<fabs(helper.ScalarProduct(&CirclePlaneNormal)) << "!" << endl; 1925 helper.ProjectOntoPlane(&CirclePlaneNormal); 1926 } 1927 radius = helper.ScalarProduct(&helper); 1928 // test whether the new center vector has length of CircleRadius 1929 if (fabs(radius - CircleRadius) > HULLEPSILON) 1930 cerr << Verbose(1) << "ERROR: The projected center of the new sphere has radius " << radius << " instead of " << CircleRadius << "." << endl; 1931 alpha = helper.Angle(&OldSphereCenter); 1932 // make the angle unique by checking the halfplanes/search direction 1933 if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON) // acos is not unique on [0, 2.*M_PI), hence extra check to decide between two half intervals 1934 alpha = 2.*M_PI - alpha; 1935 cout << Verbose(2) << "INFO: RelativeNewSphereCenter is " << helper << ", RelativeOldSphereCenter is " << OldSphereCenter << " and resulting angle is " << alpha << "." << endl; 1936 radius = helper.Distance(&OldSphereCenter); 1937 helper.ProjectOntoPlane(&NormalVector); 1938 // check whether new center is somewhat away or at least right over the current baseline to prevent intersecting triangles 1939 if ((radius > HULLEPSILON) || (helper.Norm() < HULLEPSILON)) { 1940 cout << Verbose(2) << "INFO: Distance between old and new center is " << radius << " and between new center and baseline center is " << helper.Norm() << "." << endl; 1941 return alpha; 1942 } else { 1943 cout << Verbose(1) << "ERROR: NewSphereCenter " << helper << " is too close to OldSphereCenter" << OldSphereCenter << "." << endl; 1944 return 2.*M_PI; 1945 } 1946 1946 }; 1947 1947 … … 1978 1978 // void Find_next_suitable_point(class BoundaryTriangleSet *BaseTriangle, class BoundaryLineSet *BaseLine, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC) 1979 1979 // { 1980 // 1981 // Vector CircleCenter;// center of the circle, i.e. of the band of sphere's centers1982 // 1983 // Vector OldSphereCenter;// center of the sphere defined by the three points of BaseTriangle1984 // Vector NewSphereCenter;// center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility1985 // Vector OtherNewSphereCenter;// center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility1986 // Vector NewNormalVector;// normal vector of the Candidate's triangle1987 // Vector SearchDirection;// vector that points out of BaseTriangle and is orthonormal to its NormalVector (i.e. the desired direction for the best Candidate)1988 // 1989 // 1990 // 1991 // 1992 // 1993 // 1994 // 1995 // 1980 // atom *Walker = NULL; 1981 // Vector CircleCenter; // center of the circle, i.e. of the band of sphere's centers 1982 // Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in 1983 // Vector OldSphereCenter; // center of the sphere defined by the three points of BaseTriangle 1984 // Vector NewSphereCenter; // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility 1985 // Vector OtherNewSphereCenter; // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility 1986 // Vector NewNormalVector; // normal vector of the Candidate's triangle 1987 // Vector SearchDirection; // vector that points out of BaseTriangle and is orthonormal to its NormalVector (i.e. the desired direction for the best Candidate) 1988 // Vector helper; 1989 // LinkedAtoms *List = NULL; 1990 // double CircleRadius; // radius of this circle 1991 // double radius; 1992 // double alpha, Otheralpha; // angles (i.e. parameter for the circle). 1993 // double Nullalpha; // angle between OldSphereCenter and NormalVector of base triangle 1994 // int N[NDIM], Nlower[NDIM], Nupper[NDIM]; 1995 // atom *Candidate = NULL; 1996 1996 // 1997 // 1997 // cout << Verbose(1) << "Begin of Find_next_suitable_point" << endl; 1998 1998 // 1999 // 1999 // cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << BaseTriangle->NormalVector << "." << endl; 2000 2000 // 2001 // 2002 // 2003 // 2004 // 2001 // // construct center of circle 2002 // CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x)); 2003 // CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x); 2004 // CircleCenter.Scale(0.5); 2005 2005 // 2006 // 2007 // 2008 // 2006 // // construct normal vector of circle 2007 // CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x); 2008 // CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x); 2009 2009 // 2010 // 2011 // 2012 // 2013 // 2014 // 2015 // 2010 // // calculate squared radius of circle 2011 // radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal); 2012 // if (radius/4. < RADIUS*RADIUS) { 2013 // CircleRadius = RADIUS*RADIUS - radius/4.; 2014 // CirclePlaneNormal.Normalize(); 2015 // cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl; 2016 2016 // 2017 // 2018 // 2019 // helper.CopyVector(&BaseTriangle->NormalVector);// normal vector ensures that this is correct center of the two possible ones2020 // 2021 // 2022 // 2023 // 2024 // 2017 // // construct old center 2018 // GetCenterofCircumcircle(&OldSphereCenter, &(BaseTriangle->endpoints[0]->node->x), &(BaseTriangle->endpoints[1]->node->x), &(BaseTriangle->endpoints[2]->node->x)); 2019 // helper.CopyVector(&BaseTriangle->NormalVector); // normal vector ensures that this is correct center of the two possible ones 2020 // radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&OldSphereCenter); 2021 // helper.Scale(sqrt(RADIUS*RADIUS - radius)); 2022 // OldSphereCenter.AddVector(&helper); 2023 // OldSphereCenter.SubtractVector(&CircleCenter); 2024 // cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl; 2025 2025 // 2026 // 2027 // 2028 // 2029 // 2030 // 2031 // 2032 // 2026 // // test whether old center is on the band's plane 2027 // if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) { 2028 // cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl; 2029 // OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal); 2030 // } 2031 // radius = OldSphereCenter.ScalarProduct(&OldSphereCenter); 2032 // if (fabs(radius - CircleRadius) < HULLEPSILON) { 2033 2033 // 2034 // 2035 // 2036 // 2037 // for(int i=0;i<3;i++)// just take next different endpoint2038 // 2039 // 2040 // 2041 // if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)// ohoh, SearchDirection points inwards!2042 // 2043 // 2044 // 2045 // 2046 // if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {// rotated the wrong way!2047 // 2048 // 2034 // // construct SearchDirection 2035 // SearchDirection.MakeNormalVector(&BaseTriangle->NormalVector, &CirclePlaneNormal); 2036 // helper.CopyVector(&BaseLine->endpoints[0]->node->x); 2037 // for(int i=0;i<3;i++) // just take next different endpoint 2038 // if ((BaseTriangle->endpoints[i]->node != BaseLine->endpoints[0]->node) && (BaseTriangle->endpoints[i]->node != BaseLine->endpoints[1]->node)) { 2039 // helper.SubtractVector(&BaseTriangle->endpoints[i]->node->x); 2040 // } 2041 // if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON) // ohoh, SearchDirection points inwards! 2042 // SearchDirection.Scale(-1.); 2043 // SearchDirection.ProjectOntoPlane(&OldSphereCenter); 2044 // SearchDirection.Normalize(); 2045 // cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl; 2046 // if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) { // rotated the wrong way! 2047 // cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl; 2048 // } 2049 2049 // 2050 // if (LC->SetIndexToVector(&CircleCenter)) {// get cell for the starting atom2051 // 2052 // 2053 // 2054 // 2055 // 2056 // 2057 // 2058 // 2059 // 2060 // 2061 // 2062 // 2063 // 2064 // 2065 // 2066 // 2067 // 2068 // 2069 // 2070 // 2071 // 2072 // 2073 // 2050 // if (LC->SetIndexToVector(&CircleCenter)) { // get cell for the starting atom 2051 // for(int i=0;i<NDIM;i++) // store indices of this cell 2052 // N[i] = LC->n[i]; 2053 // cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl; 2054 // } else { 2055 // cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl; 2056 // return; 2057 // } 2058 // // then go through the current and all neighbouring cells and check the contained atoms for possible candidates 2059 // cout << Verbose(2) << "LC Intervals:"; 2060 // for (int i=0;i<NDIM;i++) { 2061 // Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0; 2062 // Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1; 2063 // cout << " [" << Nlower[i] << "," << Nupper[i] << "] "; 2064 // } 2065 // cout << endl; 2066 // for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++) 2067 // for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++) 2068 // for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) { 2069 // List = LC->GetCurrentCell(); 2070 // cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl; 2071 // if (List != NULL) { 2072 // for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) { 2073 // Candidate = (*Runner); 2074 2074 // 2075 // 2076 // 2077 // 2075 // // check for three unique points 2076 // if ((Candidate != BaseTriangle->endpoints[0]->node) && (Candidate != BaseTriangle->endpoints[1]->node) && (Candidate != BaseTriangle->endpoints[2]->node)) { 2077 // cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl; 2078 2078 // 2079 // 2080 // 2081 // 2079 // // construct both new centers 2080 // GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x)); 2081 // OtherNewSphereCenter.CopyVector(&NewSphereCenter); 2082 2082 // 2083 // 2084 // 2085 // 2086 // 2087 // 2088 // 2089 // 2090 // 2091 // 2092 // 2083 // if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) { 2084 // helper.CopyVector(&NewNormalVector); 2085 // cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl; 2086 // radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter); 2087 // if (radius < RADIUS*RADIUS) { 2088 // helper.Scale(sqrt(RADIUS*RADIUS - radius)); 2089 // cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl; 2090 // NewSphereCenter.AddVector(&helper); 2091 // NewSphereCenter.SubtractVector(&CircleCenter); 2092 // cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl; 2093 2093 // 2094 // 2095 // 2096 // 2097 // 2094 // helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction 2095 // OtherNewSphereCenter.AddVector(&helper); 2096 // OtherNewSphereCenter.SubtractVector(&CircleCenter); 2097 // cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl; 2098 2098 // 2099 // 2100 // 2101 // 2102 // 2103 // 2104 // 2105 // 2106 // 2107 // 2108 // 2109 // 2110 // 2111 // 2112 // 2113 // 2114 // 2115 // 2116 // 2099 // // check both possible centers 2100 // alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection); 2101 // Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection); 2102 // alpha = min(alpha, Otheralpha); 2103 // if (*ShortestAngle > alpha) { 2104 // OptCandidate = Candidate; 2105 // *ShortestAngle = alpha; 2106 // if (alpha != Otheralpha) 2107 // OptCandidateCenter->CopyVector(&NewSphereCenter); 2108 // else 2109 // OptCandidateCenter->CopyVector(&OtherNewSphereCenter); 2110 // cout << Verbose(1) << "We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl; 2111 // } else { 2112 // if (OptCandidate != NULL) 2113 // cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl; 2114 // else 2115 // cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl; 2116 // } 2117 2117 // 2118 // 2119 // 2120 // 2121 // 2122 // 2123 // 2124 // 2125 // 2126 // 2127 // 2128 // 2129 // 2130 // 2131 // 2132 // 2133 // 2134 // 2135 // 2118 // } else { 2119 // cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl; 2120 // } 2121 // } else { 2122 // cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl; 2123 // } 2124 // } else { 2125 // cout << Verbose(1) << "REJECT: Base triangle " << *BaseTriangle << " contains Candidate " << *Candidate << "." << endl; 2126 // } 2127 // } 2128 // } 2129 // } 2130 // } else { 2131 // cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl; 2132 // } 2133 // } else { 2134 // cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and base triangle " << *BaseTriangle << " is too big!" << endl; 2135 // } 2136 2136 // 2137 // 2137 // cout << Verbose(1) << "End of Find_next_suitable_point" << endl; 2138 2138 // }; 2139 2139 … … 2148 2148 */ 2149 2149 bool Tesselation::CheckPresenceOfTriangle(ofstream *out, atom *Candidates[3]) { 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2150 LineMap::iterator FindLine; 2151 PointMap::iterator FindPoint; 2152 2153 *out << Verbose(2) << "Begin of CheckPresenceOfTriangle" << endl; 2154 for (int i=0;i<3;i++) { // check through all endpoints 2155 FindPoint = PointsOnBoundary.find(Candidates[i]->nr); 2156 if (FindPoint != PointsOnBoundary.end()) 2157 TPS[i] = FindPoint->second; 2158 else 2159 TPS[i] = NULL; 2160 } 2161 2162 // check lines 2163 for (int i=0;i<3;i++) 2164 if (TPS[i] != NULL) 2165 for (int j=i;j<3;j++) 2166 if (TPS[j] != NULL) { 2167 FindLine = TPS[i]->lines.find(TPS[j]->node->nr); 2168 if ((FindLine != TPS[i]->lines.end()) && (FindLine->second->TrianglesCount > 1)) { 2169 *out << "WARNING: Line " << *FindLine->second << " already present with " << FindLine->second->TrianglesCount << " triangles attached." << endl; 2170 *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl; 2171 return false; 2172 } 2173 } 2174 *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl; 2175 return true; 2176 2176 }; 2177 2177 … … 2211 2211 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) 2212 2212 { 2213 Vector CircleCenter;// center of the circle, i.e. of the band of sphere's centers2214 2215 Vector NewSphereCenter;// center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility2216 Vector OtherNewSphereCenter;// center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility2217 Vector NewNormalVector;// normal vector of the Candidate's triangle2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {// rotated the wrong way!2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2213 Vector CircleCenter; // center of the circle, i.e. of the band of sphere's centers 2214 Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in 2215 Vector NewSphereCenter; // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility 2216 Vector OtherNewSphereCenter; // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility 2217 Vector NewNormalVector; // normal vector of the Candidate's triangle 2218 Vector helper; 2219 LinkedAtoms *List = NULL; 2220 double CircleRadius; // radius of this circle 2221 double radius; 2222 double alpha, Otheralpha; // angles (i.e. parameter for the circle). 2223 int N[NDIM], Nlower[NDIM], Nupper[NDIM]; 2224 atom *Candidate = NULL; 2225 2226 cout << Verbose(1) << "Begin of Find_third_point_for_Tesselation" << endl; 2227 2228 cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl; 2229 2230 // construct center of circle 2231 CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x)); 2232 CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x); 2233 CircleCenter.Scale(0.5); 2234 2235 // construct normal vector of circle 2236 CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x); 2237 CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x); 2238 2239 // calculate squared radius of circle 2240 radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal); 2241 if (radius/4. < RADIUS*RADIUS) { 2242 CircleRadius = RADIUS*RADIUS - radius/4.; 2243 CirclePlaneNormal.Normalize(); 2244 cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl; 2245 2246 // test whether old center is on the band's plane 2247 if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) { 2248 cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl; 2249 OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal); 2250 } 2251 radius = OldSphereCenter.ScalarProduct(&OldSphereCenter); 2252 if (fabs(radius - CircleRadius) < HULLEPSILON) { 2253 2254 // check SearchDirection 2255 cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl; 2256 if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) { // rotated the wrong way! 2257 cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are not orthogonal!" << endl; 2258 } 2259 // get cell for the starting atom 2260 if (LC->SetIndexToVector(&CircleCenter)) { 2261 for(int i=0;i<NDIM;i++) // store indices of this cell 2262 N[i] = LC->n[i]; 2263 cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl; 2264 } else { 2265 cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl; 2266 return; 2267 } 2268 // then go through the current and all neighbouring cells and check the contained atoms for possible candidates 2269 cout << Verbose(2) << "LC Intervals:"; 2270 for (int i=0;i<NDIM;i++) { 2271 Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0; 2272 Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1; 2273 cout << " [" << Nlower[i] << "," << Nupper[i] << "] "; 2274 } 2275 cout << endl; 2276 for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++) 2277 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++) 2278 for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) { 2279 List = LC->GetCurrentCell(); 2280 //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl; 2281 if (List != NULL) { 2282 for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) { 2283 Candidate = (*Runner); 2284 2285 // check for three unique points 2286 if ((Candidate != BaseLine->endpoints[0]->node) && (Candidate != BaseLine->endpoints[1]->node) && (Candidate != ThirdNode)) { 2287 cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl; 2288 2289 // construct both new centers 2290 GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x)); 2291 OtherNewSphereCenter.CopyVector(&NewSphereCenter); 2292 2293 if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) { 2294 helper.CopyVector(&NewNormalVector); 2295 cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl; 2296 radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter); 2297 if (radius < RADIUS*RADIUS) { 2298 helper.Scale(sqrt(RADIUS*RADIUS - radius)); 2299 cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl; 2300 NewSphereCenter.AddVector(&helper); 2301 NewSphereCenter.SubtractVector(&CircleCenter); 2302 cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl; 2303 2304 helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction 2305 OtherNewSphereCenter.AddVector(&helper); 2306 OtherNewSphereCenter.SubtractVector(&CircleCenter); 2307 cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl; 2308 2309 // check both possible centers 2310 alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, NormalVector, SearchDirection); 2311 Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, NormalVector, SearchDirection); 2312 alpha = min(alpha, Otheralpha); 2313 if (*ShortestAngle > alpha) { 2314 OptCandidate = Candidate; 2315 *ShortestAngle = alpha; 2316 if (alpha != Otheralpha) 2317 OptCandidateCenter->CopyVector(&NewSphereCenter); 2318 else 2319 OptCandidateCenter->CopyVector(&OtherNewSphereCenter); 2320 cout << Verbose(1) << "ACCEPT: We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl; 2321 } else { 2322 if (OptCandidate != NULL) 2323 cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl; 2324 else 2325 cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl; 2326 } 2327 2328 } else { 2329 cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl; 2330 } 2331 } else { 2332 cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl; 2333 } 2334 } else { 2335 if (ThirdNode != NULL) 2336 cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " and " << *ThirdNode << " contains Candidate " << *Candidate << "." << endl; 2337 else 2338 cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " contains Candidate " << *Candidate << "." << endl; 2339 } 2340 } 2341 } 2342 } 2343 } else { 2344 cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl; 2345 } 2346 } else { 2347 if (ThirdNode != NULL) 2348 cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and third node " << *ThirdNode << " is too big!" << endl; 2349 else 2350 cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " is too big!" << endl; 2351 } 2352 2353 cout << Verbose(1) << "End of Find_third_point_for_Tesselation" << endl; 2354 2354 }; 2355 2355 … … 2365 2365 void Find_second_point_for_Tesselation(atom* a, atom* Candidate, Vector Oben, atom*& Opt_Candidate, double Storage[3], double RADIUS, LinkedCell *LC) 2366 2366 { 2367 2368 2369 2370 2371 2372 2373 if (LC->SetIndexToAtom(a)) {// get cell for the starting atom2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2367 cout << Verbose(2) << "Begin of Find_second_point_for_Tesselation" << endl; 2368 Vector AngleCheck; 2369 double norm = -1., angle; 2370 LinkedAtoms *List = NULL; 2371 int N[NDIM], Nlower[NDIM], Nupper[NDIM]; 2372 2373 if (LC->SetIndexToAtom(a)) { // get cell for the starting atom 2374 for(int i=0;i<NDIM;i++) // store indices of this cell 2375 N[i] = LC->n[i]; 2376 } else { 2377 cerr << "ERROR: Atom " << *a << " is not found in cell " << LC->index << "." << endl; 2378 return; 2379 } 2380 // then go through the current and all neighbouring cells and check the contained atoms for possible candidates 2381 cout << Verbose(2) << "LC Intervals:"; 2382 for (int i=0;i<NDIM;i++) { 2383 Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0; 2384 Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1; 2385 cout << " [" << Nlower[i] << "," << Nupper[i] << "] "; 2386 } 2387 cout << endl; 2388 for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++) 2389 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++) 2390 for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) { 2391 List = LC->GetCurrentCell(); 2392 //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl; 2393 if (List != NULL) { 2394 for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) { 2395 Candidate = (*Runner); 2396 // check if we only have one unique point yet ... 2397 if (a != Candidate) { 2398 cout << Verbose(3) << "Current candidate is " << *Candidate << ": "; 2399 AngleCheck.CopyVector(&(Candidate->x)); 2400 AngleCheck.SubtractVector(&(a->x)); 2401 norm = AngleCheck.Norm(); 2402 // second point shall have smallest angle with respect to Oben vector 2403 if (norm < RADIUS) { 2404 angle = AngleCheck.Angle(&Oben); 2405 if (angle < Storage[0]) { 2406 //cout << Verbose(1) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[1]); 2407 cout << "Is a better candidate with distance " << norm << " and " << angle << ".\n"; 2408 Opt_Candidate = Candidate; 2409 Storage[0] = AngleCheck.Angle(&Oben); 2410 //cout << Verbose(1) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[2]); 2411 } else { 2412 cout << "Looses with angle " << angle << " to a better candidate " << *Opt_Candidate << endl; 2413 } 2414 } else { 2415 cout << "Refused due to Radius " << norm << endl; 2416 } 2417 } 2418 } 2419 } 2420 } 2421 cout << Verbose(2) << "End of Find_second_point_for_Tesselation" << endl; 2422 2422 }; 2423 2423 … … 2431 2431 void Tesselation::Find_starting_triangle(ofstream *out, molecule *mol, const double RADIUS, LinkedCell *LC) 2432 2432 { 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 const int k = 1;// arbitrary choice2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 SearchDirection.MakeNormalVector(&Chord, &Oben);// whether we look "left" first or "right" first is not important ...2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2433 cout << Verbose(1) << "Begin of Find_starting_triangle\n"; 2434 int i = 0; 2435 LinkedAtoms *List = NULL; 2436 atom* FirstPoint; 2437 atom* SecondPoint; 2438 atom* MaxAtom[NDIM]; 2439 double max_coordinate[NDIM]; 2440 Vector Oben; 2441 Vector helper; 2442 Vector Chord; 2443 Vector SearchDirection; 2444 Vector OptCandidateCenter; 2445 2446 Oben.Zero(); 2447 2448 for (i = 0; i < 3; i++) { 2449 MaxAtom[i] = NULL; 2450 max_coordinate[i] = -1; 2451 } 2452 2453 // 1. searching topmost atom with respect to each axis 2454 for (int i=0;i<NDIM;i++) { // each axis 2455 LC->n[i] = LC->N[i]-1; // current axis is topmost cell 2456 for (LC->n[(i+1)%NDIM]=0;LC->n[(i+1)%NDIM]<LC->N[(i+1)%NDIM];LC->n[(i+1)%NDIM]++) 2457 for (LC->n[(i+2)%NDIM]=0;LC->n[(i+2)%NDIM]<LC->N[(i+2)%NDIM];LC->n[(i+2)%NDIM]++) { 2458 List = LC->GetCurrentCell(); 2459 //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl; 2460 if (List != NULL) { 2461 for (LinkedAtoms::iterator Runner = List->begin();Runner != List->end();Runner++) { 2462 cout << Verbose(2) << "Current atom is " << *(*Runner) << "." << endl; 2463 if ((*Runner)->x.x[i] > max_coordinate[i]) { 2464 max_coordinate[i] = (*Runner)->x.x[i]; 2465 MaxAtom[i] = (*Runner); 2466 } 2467 } 2468 } else { 2469 cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << " is invalid!" << endl; 2470 } 2471 } 2472 } 2473 2474 cout << Verbose(2) << "Found maximum coordinates: "; 2475 for (int i=0;i<NDIM;i++) 2476 cout << i << ": " << *MaxAtom[i] << "\t"; 2477 cout << endl; 2478 const int k = 1; // arbitrary choice 2479 Oben.x[k] = 1.; 2480 FirstPoint = MaxAtom[k]; 2481 cout << Verbose(1) << "Coordinates of start atom " << *FirstPoint << " at " << FirstPoint->x << "." << endl; 2482 2483 // add first point 2484 AddTrianglePoint(FirstPoint, 0); 2485 2486 double ShortestAngle; 2487 atom* Opt_Candidate = NULL; 2488 ShortestAngle = 999999.; // This will contain the angle, which will be always positive (when looking for second point), when looking for third point this will be the quadrant. 2489 2490 Find_second_point_for_Tesselation(FirstPoint, NULL, Oben, Opt_Candidate, &ShortestAngle, RADIUS, LC); // we give same point as next candidate as its bonds are looked into in find_second_... 2491 SecondPoint = Opt_Candidate; 2492 cout << Verbose(1) << "Found second point is " << *SecondPoint << " at " << SecondPoint->x << ".\n"; 2493 2494 // add second point and first baseline 2495 AddTrianglePoint(SecondPoint, 1); 2496 AddTriangleLine(TPS[0], TPS[1], 0); 2497 2498 helper.CopyVector(&(FirstPoint->x)); 2499 helper.SubtractVector(&(SecondPoint->x)); 2500 helper.Normalize(); 2501 Oben.ProjectOntoPlane(&helper); 2502 Oben.Normalize(); 2503 helper.VectorProduct(&Oben); 2504 ShortestAngle = 2.*M_PI; // This will indicate the quadrant. 2505 2506 Chord.CopyVector(&(FirstPoint->x)); // bring into calling function 2507 Chord.SubtractVector(&(SecondPoint->x)); 2508 double radius = Chord.ScalarProduct(&Chord); 2509 double CircleRadius = sqrt(RADIUS*RADIUS - radius/4.); 2510 helper.CopyVector(&Oben); 2511 helper.Scale(CircleRadius); 2512 // Now, oben and helper are two orthonormalized vectors in the plane defined by Chord (not normalized) 2513 2514 cout << Verbose(2) << "Looking for third point candidates \n"; 2515 // look in one direction of baseline for initial candidate 2516 Opt_Candidate = NULL; 2517 SearchDirection.MakeNormalVector(&Chord, &Oben); // whether we look "left" first or "right" first is not important ... 2518 2519 cout << Verbose(1) << "Looking for third point candidates ...\n"; 2520 Find_third_point_for_Tesselation(Oben, SearchDirection, helper, BLS[0], NULL, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC); 2521 cout << Verbose(1) << "Third Point is " << *Opt_Candidate << endl; 2522 2523 // add third point 2524 AddTrianglePoint(Opt_Candidate, 2); 2525 2526 // FOUND Starting Triangle: FirstPoint, SecondPoint, Opt_Candidate 2527 2528 // Finally, we only have to add the found further lines 2529 AddTriangleLine(TPS[1], TPS[2], 1); 2530 AddTriangleLine(TPS[0], TPS[2], 2); 2531 // ... and triangles to the Maps of the Tesselation class 2532 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 2533 AddTriangleToLines(); 2534 // ... and calculate its normal vector (with correct orientation) 2535 OptCandidateCenter.Scale(-1.); 2536 cout << Verbose(2) << "Oben is currently " << OptCandidateCenter << "." << endl; 2537 BTS->GetNormalVector(OptCandidateCenter); 2538 cout << Verbose(0) << "==> The found starting triangle consists of " << *FirstPoint << ", " << *SecondPoint << " and " << *Opt_Candidate << " with normal vector " << BTS->NormalVector << ".\n"; 2539 cout << Verbose(2) << "Projection is " << BTS->NormalVector.Projection(&Oben) << "." << endl; 2540 cout << Verbose(1) << "End of Find_starting_triangle\n"; 2541 2541 }; 2542 2542 … … 2552 2552 */ 2553 2553 bool Tesselation::Find_next_suitable_triangle(ofstream *out, 2554 2555 2556 { 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 helper.CopyVector(&T.NormalVector);// normal vector ensures that this is correct center of the two possible ones2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)// ohoh, SearchDirection points inwards!2608 2609 2610 2611 2612 if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {// rotated the wrong way!2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 *tempstream << "8\n 25.0 0.6 -1.0 -1.0 -1.0 0.20 0 0 0\n";2701 *tempstream << "2\n" << OptCandidateCenter.x[0] << " " << OptCandidateCenter.x[1] << " " << OptCandidateCenter.x[2] << "\t" << RADIUS << "\t1 0 0\n";2702 *tempstream << "9\nterminating special property\n";2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2554 molecule *mol, BoundaryLineSet &Line, BoundaryTriangleSet &T, 2555 const double& RADIUS, int N, const char *tempbasename, LinkedCell *LC) 2556 { 2557 cout << Verbose(1) << "Begin of Find_next_suitable_triangle\n"; 2558 ofstream *tempstream = NULL; 2559 char NumberName[255]; 2560 2561 atom* Opt_Candidate = NULL; 2562 Vector OptCandidateCenter; 2563 2564 Vector CircleCenter; 2565 Vector CirclePlaneNormal; 2566 Vector OldSphereCenter; 2567 Vector SearchDirection; 2568 Vector helper; 2569 atom *ThirdNode = NULL; 2570 double ShortestAngle = 2.*M_PI; // This will indicate the quadrant. 2571 double radius, CircleRadius; 2572 2573 cout << Verbose(1) << "Current baseline is " << Line << " of triangle " << T << "." << endl; 2574 for (int i=0;i<3;i++) 2575 if ((T.endpoints[i]->node != Line.endpoints[0]->node) && (T.endpoints[i]->node != Line.endpoints[1]->node)) 2576 ThirdNode = T.endpoints[i]->node; 2577 2578 // construct center of circle 2579 CircleCenter.CopyVector(&Line.endpoints[0]->node->x); 2580 CircleCenter.AddVector(&Line.endpoints[1]->node->x); 2581 CircleCenter.Scale(0.5); 2582 2583 // construct normal vector of circle 2584 CirclePlaneNormal.CopyVector(&Line.endpoints[0]->node->x); 2585 CirclePlaneNormal.SubtractVector(&Line.endpoints[1]->node->x); 2586 2587 // calculate squared radius of circle 2588 radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal); 2589 if (radius/4. < RADIUS*RADIUS) { 2590 CircleRadius = RADIUS*RADIUS - radius/4.; 2591 CirclePlaneNormal.Normalize(); 2592 cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl; 2593 2594 // construct old center 2595 GetCenterofCircumcircle(&OldSphereCenter, &(T.endpoints[0]->node->x), &(T.endpoints[1]->node->x), &(T.endpoints[2]->node->x)); 2596 helper.CopyVector(&T.NormalVector); // normal vector ensures that this is correct center of the two possible ones 2597 radius = Line.endpoints[0]->node->x.DistanceSquared(&OldSphereCenter); 2598 helper.Scale(sqrt(RADIUS*RADIUS - radius)); 2599 OldSphereCenter.AddVector(&helper); 2600 OldSphereCenter.SubtractVector(&CircleCenter); 2601 cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl; 2602 2603 // construct SearchDirection 2604 SearchDirection.MakeNormalVector(&T.NormalVector, &CirclePlaneNormal); 2605 helper.CopyVector(&Line.endpoints[0]->node->x); 2606 helper.SubtractVector(&ThirdNode->x); 2607 if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON) // ohoh, SearchDirection points inwards! 2608 SearchDirection.Scale(-1.); 2609 SearchDirection.ProjectOntoPlane(&OldSphereCenter); 2610 SearchDirection.Normalize(); 2611 cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl; 2612 if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) { // rotated the wrong way! 2613 cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl; 2614 } 2615 2616 // add third point 2617 cout << Verbose(1) << "Looking for third point candidates for triangle ... " << endl; 2618 Find_third_point_for_Tesselation(T.NormalVector, SearchDirection, OldSphereCenter, &Line, ThirdNode, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC); 2619 2620 } else { 2621 cout << Verbose(1) << "Circumcircle for base line " << Line << " and base triangle " << T << " is too big!" << endl; 2622 } 2623 2624 if (Opt_Candidate == NULL) { 2625 cerr << "WARNING: Could not find a suitable candidate." << endl; 2626 return false; 2627 } 2628 cout << Verbose(1) << " Optimal candidate is " << *Opt_Candidate << " with circumsphere's center at " << OptCandidateCenter << "." << endl; 2629 2630 // check whether all edges of the new triangle still have space for one more triangle (i.e. TriangleCount <2) 2631 atom *AtomCandidates[3]; 2632 AtomCandidates[0] = Opt_Candidate; 2633 AtomCandidates[1] = Line.endpoints[0]->node; 2634 AtomCandidates[2] = Line.endpoints[1]->node; 2635 bool flag = CheckPresenceOfTriangle(out, AtomCandidates); 2636 2637 if (flag) { // if so, add 2638 AddTrianglePoint(Opt_Candidate, 0); 2639 AddTrianglePoint(Line.endpoints[0]->node, 1); 2640 AddTrianglePoint(Line.endpoints[1]->node, 2); 2641 2642 AddTriangleLine(TPS[0], TPS[1], 0); 2643 AddTriangleLine(TPS[0], TPS[2], 1); 2644 AddTriangleLine(TPS[1], TPS[2], 2); 2645 2646 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 2647 AddTriangleToLines(); 2648 2649 OptCandidateCenter.Scale(-1.); 2650 BTS->GetNormalVector(OptCandidateCenter); 2651 OptCandidateCenter.Scale(-1.); 2652 2653 cout << "--> New triangle with " << *BTS << " and normal vector " << BTS->NormalVector << " for this triangle ... " << endl; 2654 cout << Verbose(1) << "We have "<< TrianglesOnBoundaryCount << " for line " << Line << "." << endl; 2655 } else { // else, yell and do nothing 2656 cout << Verbose(1) << "This triangle consisting of "; 2657 cout << *Opt_Candidate << ", "; 2658 cout << *Line.endpoints[0]->node << " and "; 2659 cout << *Line.endpoints[1]->node << " "; 2660 cout << "is invalid!" << endl; 2661 return false; 2662 } 2663 2664 if (flag && (DoSingleStepOutput && (TrianglesOnBoundaryCount % 10 == 0))) { // if we have a new triangle and want to output each new triangle configuration 2665 sprintf(NumberName, "-%04d-%s_%s_%s", TriangleFilesWritten, BTS->endpoints[0]->node->Name, BTS->endpoints[1]->node->Name, BTS->endpoints[2]->node->Name); 2666 if (DoTecplotOutput) { 2667 string NameofTempFile(tempbasename); 2668 NameofTempFile.append(NumberName); 2669 for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos)) 2670 NameofTempFile.erase(npos, 1); 2671 NameofTempFile.append(TecplotSuffix); 2672 cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 2673 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 2674 write_tecplot_file(out, tempstream, this, mol, TriangleFilesWritten); 2675 tempstream->close(); 2676 tempstream->flush(); 2677 delete(tempstream); 2678 } 2679 2680 if (DoRaster3DOutput) { 2681 string NameofTempFile(tempbasename); 2682 NameofTempFile.append(NumberName); 2683 for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos)) 2684 NameofTempFile.erase(npos, 1); 2685 NameofTempFile.append(Raster3DSuffix); 2686 cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 2687 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 2688 write_raster3d_file(out, tempstream, this, mol); 2689 // include the current position of the virtual sphere in the temporary raster3d file 2690 // make the circumsphere's center absolute again 2691 helper.CopyVector(&Line.endpoints[0]->node->x); 2692 helper.AddVector(&Line.endpoints[1]->node->x); 2693 helper.Scale(0.5); 2694 OptCandidateCenter.AddVector(&helper); 2695 Vector *center = mol->DetermineCenterOfAll(out); 2696 OptCandidateCenter.AddVector(center); 2697 delete(center); 2698 // and add to file plus translucency object 2699 *tempstream << "# current virtual sphere\n"; 2700 *tempstream << "8\n 25.0 0.6 -1.0 -1.0 -1.0 0.2 0 0 0 0\n"; 2701 *tempstream << "2\n " << OptCandidateCenter.x[0] << " " << OptCandidateCenter.x[1] << " " << OptCandidateCenter.x[2] << "\t" << RADIUS << "\t1 0 0\n"; 2702 *tempstream << "9\n terminating special property\n"; 2703 tempstream->close(); 2704 tempstream->flush(); 2705 delete(tempstream); 2706 } 2707 if (DoTecplotOutput || DoRaster3DOutput) 2708 TriangleFilesWritten++; 2709 } 2710 2711 cout << Verbose(1) << "End of Find_next_suitable_triangle\n"; 2712 return true; 2713 2713 }; 2714 2714 … … 2723 2723 void Find_non_convex_border(ofstream *out, molecule* mol, class Tesselation *Tess, class LinkedCell *LCList, const char *filename, const double RADIUS) 2724 2724 { 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 bool flag = false;// marks whether we went once through all baselines without finding any without two triangles2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 baseline = Tess->LinesOnBoundary.begin();// restart if we reach end due to newly inserted lines2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2725 int N = 0; 2726 bool freeTess = false; 2727 *out << Verbose(1) << "Entering search for non convex hull. " << endl; 2728 if (Tess == NULL) { 2729 *out << Verbose(1) << "Allocating Tesselation struct ..." << endl; 2730 Tess = new Tesselation; 2731 freeTess = true; 2732 } 2733 bool freeLC = false; 2734 LineMap::iterator baseline; 2735 *out << Verbose(0) << "Begin of Find_non_convex_border\n"; 2736 bool flag = false; // marks whether we went once through all baselines without finding any without two triangles 2737 bool failflag = false; 2738 2739 if (LCList == NULL) { 2740 LCList = new LinkedCell(mol, 2.*RADIUS); 2741 freeLC = true; 2742 } 2743 2744 Tess->Find_starting_triangle(out, mol, RADIUS, LCList); 2745 2746 baseline = Tess->LinesOnBoundary.begin(); 2747 while ((baseline != Tess->LinesOnBoundary.end()) || (flag)) { 2748 if (baseline->second->TrianglesCount == 1) { 2749 failflag = Tess->Find_next_suitable_triangle(out, mol, *(baseline->second), *(((baseline->second->triangles.begin()))->second), RADIUS, N, filename, LCList); //the line is there, so there is a triangle, but only one. 2750 flag = flag || failflag; 2751 if (!failflag) 2752 cerr << "WARNING: Find_next_suitable_triangle failed." << endl; 2753 } else { 2754 cout << Verbose(1) << "Line " << *baseline->second << " has " << baseline->second->TrianglesCount << " triangles adjacent" << endl; 2755 } 2756 N++; 2757 baseline++; 2758 if ((baseline == Tess->LinesOnBoundary.end()) && (flag)) { 2759 baseline = Tess->LinesOnBoundary.begin(); // restart if we reach end due to newly inserted lines 2760 flag = false; 2761 } 2762 } 2763 if (1) { //failflag) { 2764 *out << Verbose(1) << "Writing final tecplot file\n"; 2765 if (DoTecplotOutput) { 2766 string OutputName(filename); 2767 OutputName.append(TecplotSuffix); 2768 ofstream *tecplot = new ofstream(OutputName.c_str()); 2769 write_tecplot_file(out, tecplot, Tess, mol, -1); 2770 tecplot->close(); 2771 delete(tecplot); 2772 } 2773 if (DoRaster3DOutput) { 2774 string OutputName(filename); 2775 OutputName.append(Raster3DSuffix); 2776 ofstream *raster = new ofstream(OutputName.c_str()); 2777 write_raster3d_file(out, raster, Tess, mol); 2778 raster->close(); 2779 delete(raster); 2780 } 2781 } else { 2782 cerr << "ERROR: Could definately not find all necessary triangles!" << endl; 2783 } 2784 if (freeTess) 2785 delete(Tess); 2786 if (freeLC) 2787 delete(LCList); 2788 *out << Verbose(0) << "End of Find_non_convex_border\n"; 2789 2789 }; 2790 2790 -
src/boundary.hpp
r178f92 r437922 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 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 *Candidates[3]); 95 void Find_next_suitable_point_via_Angle_of_Sphere(atom* a, atom* b, atom* c, atom* Candidate, atom* Parent, int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint, atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol); 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 -
src/builder.cpp
r178f92 r437922 15 15 * \section about About the Program 16 16 * 17 * 18 * 19 * 17 * Molecuilder is a short program, written in C++, that enables the construction of a coordinate set for the 18 * atoms making up an molecule by the successive statement of binding angles and distances and referencing to 19 * already constructed atoms. 20 20 * 21 * 22 * 21 * A configuration file may be written that is compatible to the format used by PCP - a parallel Car-Parrinello 22 * molecular dynamics implementation. 23 23 * 24 24 * \section install Installation 25 25 * 26 * 27 * 28 * 29 * 26 * Installation should without problems succeed as follows: 27 * -# ./configure (or: mkdir build;mkdir run;cd build; ../configure --bindir=../run) 28 * -# make 29 * -# make install 30 30 * 31 * 32 * 33 * 31 * Further useful commands are 32 * -# make clean uninstall: deletes .o-files and removes executable from the given binary directory\n 33 * -# make doxygen-doc: Creates these html pages out of the documented source 34 34 * 35 35 * \section run Running 36 36 * 37 * 37 * The program can be executed by running: ./molecuilder 38 38 * 39 * 40 * 41 * 39 * Note, that it uses a database, called "elements.db", in the executable's directory. If the file is not found, 40 * it is created and any given data on elements of the periodic table will be stored therein and re-used on 41 * later re-execution. 42 42 * 43 43 * \section ref References 44 44 * 45 * 45 * For the special configuration file format, see the documentation of pcp. 46 46 * 47 47 */ … … 63 63 static void AddAtoms(periodentafel *periode, molecule *mol) 64 64 { 65 66 67 Vector x,y,z,n;// coordinates for absolute point in cell volume68 69 char choice;// menu choice char70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 65 atom *first, *second, *third, *fourth; 66 Vector **atoms; 67 Vector x,y,z,n; // coordinates for absolute point in cell volume 68 double a,b,c; 69 char choice; // menu choice char 70 bool valid; 71 72 cout << Verbose(0) << "===========ADD ATOM============================" << endl; 73 cout << Verbose(0) << " a - state absolute coordinates of atom" << endl; 74 cout << Verbose(0) << " b - state relative coordinates of atom wrt to reference point" << endl; 75 cout << Verbose(0) << " c - state relative coordinates of atom wrt to already placed atom" << endl; 76 cout << Verbose(0) << " d - state two atoms, two angles and a distance" << endl; 77 cout << Verbose(0) << " e - least square distance position to a set of atoms" << endl; 78 cout << Verbose(0) << "all else - go back" << endl; 79 cout << Verbose(0) << "===============================================" << endl; 80 cout << Verbose(0) << "Note: Specifiy angles in degrees not multiples of Pi!" << endl; 81 cout << Verbose(0) << "INPUT: "; 82 cin >> choice; 83 84 switch (choice) { 85 85 default: 86 86 cout << Verbose(0) << "Not a valid choice." << endl; 87 87 break; 88 88 case 'a': // absolute coordinates of atom 89 89 cout << Verbose(0) << "Enter absolute coordinates." << endl; 90 90 first = new atom; 91 91 first->x.AskPosition(mol->cell_size, false); 92 first->type = periode->AskElement(); 93 mol->AddAtom(first); 94 95 96 92 first->type = periode->AskElement(); // give type 93 mol->AddAtom(first); // add to molecule 94 break; 95 96 case 'b': // relative coordinates of atom wrt to reference point 97 97 first = new atom; 98 98 valid = true; … … 106 106 cout << Verbose(0) << "\n"; 107 107 } while (!(valid = mol->CheckBounds((const Vector *)&first->x))); 108 first->type = periode->AskElement(); 109 mol->AddAtom(first); 110 111 112 108 first->type = periode->AskElement(); // give type 109 mol->AddAtom(first); // add to molecule 110 break; 111 112 case 'c': // relative coordinates of atom wrt to already placed atom 113 113 first = new atom; 114 114 valid = true; … … 122 122 } 123 123 } while (!(valid = mol->CheckBounds((const Vector *)&first->x))); 124 first->type = periode->AskElement(); 125 mol->AddAtom(first); 124 first->type = periode->AskElement(); // give type 125 mol->AddAtom(first); // add to molecule 126 126 break; 127 127 … … 224 224 cout << Verbose(0) << endl; 225 225 } while (!(valid = mol->CheckBounds((const Vector *)&first->x))); 226 first->type = periode->AskElement(); 227 mol->AddAtom(first); 228 229 230 226 first->type = periode->AskElement(); // give type 227 mol->AddAtom(first); // add to molecule 228 break; 229 230 case 'e': // least square distance position to a set of atoms 231 231 first = new atom; 232 232 atoms = new (Vector*[128]); … … 248 248 249 249 first->x.Output((ofstream *)&cout); 250 first->type = periode->AskElement(); 251 mol->AddAtom(first); 250 first->type = periode->AskElement(); // give type 251 mol->AddAtom(first); // add to molecule 252 252 } else { 253 253 delete first; 254 254 cout << Verbose(0) << "Please enter at least two vectors!\n"; 255 255 } 256 257 256 break; 257 }; 258 258 }; 259 259 … … 263 263 static void CenterAtoms(molecule *mol) 264 264 { 265 266 char choice;// menu choice char267 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 mol->CenterEdge((ofstream *)&cout, &x);// make every coordinate positive297 298 299 300 301 mol->SetBoxDimension(&helper);// update Box of atoms by boundary302 303 304 305 306 307 308 309 310 311 312 313 314 265 Vector x, y, helper; 266 char choice; // menu choice char 267 268 cout << Verbose(0) << "===========CENTER ATOMS=========================" << endl; 269 cout << Verbose(0) << " a - on origin" << endl; 270 cout << Verbose(0) << " b - on center of gravity" << endl; 271 cout << Verbose(0) << " c - within box with additional boundary" << endl; 272 cout << Verbose(0) << " d - within given simulation box" << endl; 273 cout << Verbose(0) << "all else - go back" << endl; 274 cout << Verbose(0) << "===============================================" << endl; 275 cout << Verbose(0) << "INPUT: "; 276 cin >> choice; 277 278 switch (choice) { 279 default: 280 cout << Verbose(0) << "Not a valid choice." << endl; 281 break; 282 case 'a': 283 cout << Verbose(0) << "Centering atoms in config file on origin." << endl; 284 mol->CenterOrigin((ofstream *)&cout); 285 break; 286 case 'b': 287 cout << Verbose(0) << "Centering atoms in config file on center of gravity." << endl; 288 mol->CenterPeriodic((ofstream *)&cout); 289 break; 290 case 'c': 291 cout << Verbose(0) << "Centering atoms in config file within given additional boundary." << endl; 292 for (int i=0;i<NDIM;i++) { 293 cout << Verbose(0) << "Enter axis " << i << " boundary: "; 294 cin >> y.x[i]; 295 } 296 mol->CenterEdge((ofstream *)&cout, &x); // make every coordinate positive 297 mol->Center.AddVector(&y); // translate by boundary 298 helper.CopyVector(&y); 299 helper.Scale(2.); 300 helper.AddVector(&x); 301 mol->SetBoxDimension(&helper); // update Box of atoms by boundary 302 break; 303 case 'd': 304 cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl; 305 for (int i=0;i<NDIM;i++) { 306 cout << Verbose(0) << "Enter axis " << i << " boundary: "; 307 cin >> x.x[i]; 308 } 309 // center 310 mol->CenterInBox((ofstream *)&cout, &x); 311 // update Box of atoms by boundary 312 mol->SetBoxDimension(&x); 313 break; 314 } 315 315 }; 316 316 … … 321 321 static void AlignAtoms(periodentafel *periode, molecule *mol) 322 322 { 323 324 325 char choice;// menu choice char326 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 370 371 372 373 374 375 376 377 378 379 380 381 382 383 323 atom *first, *second, *third; 324 Vector x,n; 325 char choice; // menu choice char 326 327 cout << Verbose(0) << "===========ALIGN ATOMS=========================" << endl; 328 cout << Verbose(0) << " a - state three atoms defining align plane" << endl; 329 cout << Verbose(0) << " b - state alignment vector" << endl; 330 cout << Verbose(0) << " c - state two atoms in alignment direction" << endl; 331 cout << Verbose(0) << " d - align automatically by least square fit" << endl; 332 cout << Verbose(0) << "all else - go back" << endl; 333 cout << Verbose(0) << "===============================================" << endl; 334 cout << Verbose(0) << "INPUT: "; 335 cin >> choice; 336 337 switch (choice) { 338 default: 339 case 'a': // three atoms defining mirror plane 340 first = mol->AskAtom("Enter first atom: "); 341 second = mol->AskAtom("Enter second atom: "); 342 third = mol->AskAtom("Enter third atom: "); 343 344 n.MakeNormalVector((const Vector *)&first->x,(const Vector *)&second->x,(const Vector *)&third->x); 345 break; 346 case 'b': // normal vector of mirror plane 347 cout << Verbose(0) << "Enter normal vector of mirror plane." << endl; 348 n.AskPosition(mol->cell_size,0); 349 n.Normalize(); 350 break; 351 case 'c': // three atoms defining mirror plane 352 first = mol->AskAtom("Enter first atom: "); 353 second = mol->AskAtom("Enter second atom: "); 354 355 n.CopyVector((const Vector *)&first->x); 356 n.SubtractVector((const Vector *)&second->x); 357 n.Normalize(); 358 break; 359 case 'd': 360 char shorthand[4]; 361 Vector a; 362 struct lsq_params param; 363 do { 364 fprintf(stdout, "Enter the element of atoms to be chosen: "); 365 fscanf(stdin, "%3s", shorthand); 366 } while ((param.type = periode->FindElement(shorthand)) == NULL); 367 cout << Verbose(0) << "Element is " << param.type->name << endl; 368 mol->GetAlignvector(¶m); 369 for (int i=NDIM;i--;) { 370 x.x[i] = gsl_vector_get(param.x,i); 371 n.x[i] = gsl_vector_get(param.x,i+NDIM); 372 } 373 gsl_vector_free(param.x); 374 cout << Verbose(0) << "Offset vector: "; 375 x.Output((ofstream *)&cout); 376 cout << Verbose(0) << endl; 377 n.Normalize(); 378 break; 379 }; 380 cout << Verbose(0) << "Alignment vector: "; 381 n.Output((ofstream *)&cout); 382 cout << Verbose(0) << endl; 383 mol->Align(&n); 384 384 }; 385 385 … … 389 389 static void MirrorAtoms(molecule *mol) 390 390 { 391 392 393 char choice;// menu choice char394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 391 atom *first, *second, *third; 392 Vector n; 393 char choice; // menu choice char 394 395 cout << Verbose(0) << "===========MIRROR ATOMS=========================" << endl; 396 cout << Verbose(0) << " a - state three atoms defining mirror plane" << endl; 397 cout << Verbose(0) << " b - state normal vector of mirror plane" << endl; 398 cout << Verbose(0) << " c - state two atoms in normal direction" << endl; 399 cout << Verbose(0) << "all else - go back" << endl; 400 cout << Verbose(0) << "===============================================" << endl; 401 cout << Verbose(0) << "INPUT: "; 402 cin >> choice; 403 404 switch (choice) { 405 default: 406 case 'a': // three atoms defining mirror plane 407 first = mol->AskAtom("Enter first atom: "); 408 second = mol->AskAtom("Enter second atom: "); 409 third = mol->AskAtom("Enter third atom: "); 410 411 n.MakeNormalVector((const Vector *)&first->x,(const Vector *)&second->x,(const Vector *)&third->x); 412 break; 413 case 'b': // normal vector of mirror plane 414 cout << Verbose(0) << "Enter normal vector of mirror plane." << endl; 415 n.AskPosition(mol->cell_size,0); 416 n.Normalize(); 417 break; 418 case 'c': // three atoms defining mirror plane 419 first = mol->AskAtom("Enter first atom: "); 420 second = mol->AskAtom("Enter second atom: "); 421 422 n.CopyVector((const Vector *)&first->x); 423 n.SubtractVector((const Vector *)&second->x); 424 n.Normalize(); 425 break; 426 }; 427 cout << Verbose(0) << "Normal vector: "; 428 n.Output((ofstream *)&cout); 429 cout << Verbose(0) << endl; 430 mol->Mirror((const Vector *)&n); 431 431 }; 432 432 … … 436 436 static void RemoveAtoms(molecule *mol) 437 437 { 438 439 440 441 char choice;// menu choice char442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 438 atom *first, *second; 439 int axis; 440 double tmp1, tmp2; 441 char choice; // menu choice char 442 443 cout << Verbose(0) << "===========REMOVE ATOMS=========================" << endl; 444 cout << Verbose(0) << " a - state atom for removal by number" << endl; 445 cout << Verbose(0) << " b - keep only in radius around atom" << endl; 446 cout << Verbose(0) << " c - remove this with one axis greater value" << endl; 447 cout << Verbose(0) << "all else - go back" << endl; 448 cout << Verbose(0) << "===============================================" << endl; 449 cout << Verbose(0) << "INPUT: "; 450 cin >> choice; 451 452 switch (choice) { 453 default: 454 case 'a': 455 if (mol->RemoveAtom(mol->AskAtom("Enter number of atom within molecule: "))) 456 cout << Verbose(1) << "Atom removed." << endl; 457 else 458 cout << Verbose(1) << "Atom not found." << endl; 459 break; 460 case 'b': 461 second = mol->AskAtom("Enter number of atom as reference point: "); 462 cout << Verbose(0) << "Enter radius: "; 463 cin >> tmp1; 464 first = mol->start; 465 while(first->next != mol->end) { 466 first = first->next; 467 if (first->x.DistanceSquared((const Vector *)&second->x) > tmp1*tmp1) // distance to first above radius ... 468 mol->RemoveAtom(first); 469 } 470 break; 471 case 'c': 472 cout << Verbose(0) << "Which axis is it: "; 473 cin >> axis; 474 cout << Verbose(0) << "Left inward boundary: "; 475 cin >> tmp1; 476 cout << Verbose(0) << "Right inward boundary: "; 477 cin >> tmp2; 478 first = mol->start; 479 while(first->next != mol->end) { 480 first = first->next; 481 if ((first->x.x[axis] > tmp2) || (first->x.x[axis] < tmp1)) // out of boundary ... 482 mol->RemoveAtom(first); 483 } 484 break; 485 }; 486 //mol->Output((ofstream *)&cout); 487 choice = 'r'; 488 488 }; 489 489 … … 494 494 static void MeasureAtoms(periodentafel *periode, molecule *mol, config *configuration) 495 495 { 496 497 498 499 500 char choice;// menu choice char501 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 third= mol->AskAtom("Enter last atom: ");559 560 561 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 587 588 589 590 591 592 593 594 595 596 597 598 496 atom *first, *second, *third; 497 Vector x,y; 498 double min[256], tmp1, tmp2, tmp3; 499 int Z; 500 char choice; // menu choice char 501 502 cout << Verbose(0) << "===========MEASURE ATOMS=========================" << endl; 503 cout << Verbose(0) << " a - calculate bond length between one atom and all others" << endl; 504 cout << Verbose(0) << " b - calculate bond length between two atoms" << endl; 505 cout << Verbose(0) << " c - calculate bond angle" << endl; 506 cout << Verbose(0) << " d - calculate principal axis of the system" << endl; 507 cout << Verbose(0) << " e - calculate volume of the convex envelope" << endl; 508 cout << Verbose(0) << " f - calculate temperature from current velocity" << endl; 509 cout << Verbose(0) << " g - output all temperatures per step from velocities" << endl; 510 cout << Verbose(0) << "all else - go back" << endl; 511 cout << Verbose(0) << "===============================================" << endl; 512 cout << Verbose(0) << "INPUT: "; 513 cin >> choice; 514 515 switch(choice) { 516 default: 517 cout << Verbose(1) << "Not a valid choice." << endl; 518 break; 519 case 'a': 520 first = mol->AskAtom("Enter first atom: "); 521 for (int i=MAX_ELEMENTS;i--;) 522 min[i] = 0.; 523 524 second = mol->start; 525 while ((second->next != mol->end)) { 526 second = second->next; // advance 527 Z = second->type->Z; 528 tmp1 = 0.; 529 if (first != second) { 530 x.CopyVector((const Vector *)&first->x); 531 x.SubtractVector((const Vector *)&second->x); 532 tmp1 = x.Norm(); 533 } 534 if ((tmp1 != 0.) && ((min[Z] == 0.) || (tmp1 < min[Z]))) min[Z] = tmp1; 535 //cout << Verbose(0) << "Bond length between Atom " << first->nr << " and " << second->nr << ": " << tmp1 << " a.u." << endl; 536 } 537 for (int i=MAX_ELEMENTS;i--;) 538 if (min[i] != 0.) cout << Verbose(0) << "Minimum Bond length between " << first->type->name << " Atom " << first->nr << " and next Ion of type " << (periode->FindElement(i))->name << ": " << min[i] << " a.u." << endl; 539 break; 540 541 case 'b': 542 first = mol->AskAtom("Enter first atom: "); 543 second = mol->AskAtom("Enter second atom: "); 544 for (int i=NDIM;i--;) 545 min[i] = 0.; 546 x.CopyVector((const Vector *)&first->x); 547 x.SubtractVector((const Vector *)&second->x); 548 tmp1 = x.Norm(); 549 cout << Verbose(1) << "Distance vector is "; 550 x.Output((ofstream *)&cout); 551 cout << "." << endl << "Norm of distance is " << tmp1 << "." << endl; 552 break; 553 554 case 'c': 555 cout << Verbose(0) << "Evaluating bond angle between three - first, central, last - atoms." << endl; 556 first = mol->AskAtom("Enter first atom: "); 557 second = mol->AskAtom("Enter central atom: "); 558 third = mol->AskAtom("Enter last atom: "); 559 tmp1 = tmp2 = tmp3 = 0.; 560 x.CopyVector((const Vector *)&first->x); 561 x.SubtractVector((const Vector *)&second->x); 562 y.CopyVector((const Vector *)&third->x); 563 y.SubtractVector((const Vector *)&second->x); 564 cout << Verbose(0) << "Bond angle between first atom Nr." << first->nr << ", central atom Nr." << second->nr << " and last atom Nr." << third->nr << ": "; 565 cout << Verbose(0) << (acos(x.ScalarProduct((const Vector *)&y)/(y.Norm()*x.Norm()))/M_PI*180.) << " degrees" << endl; 566 break; 567 case 'd': 568 cout << Verbose(0) << "Evaluating prinicipal axis." << endl; 569 cout << Verbose(0) << "Shall we rotate? [0/1]: "; 570 cin >> Z; 571 if ((Z >=0) && (Z <=1)) 572 mol->PrincipalAxisSystem((ofstream *)&cout, (bool)Z); 573 else 574 mol->PrincipalAxisSystem((ofstream *)&cout, false); 575 break; 576 case 'e': 577 cout << Verbose(0) << "Evaluating volume of the convex envelope."; 578 VolumeOfConvexEnvelope((ofstream *)&cout, NULL, configuration, NULL, mol); 579 break; 580 case 'f': 581 mol->OutputTemperatureFromTrajectories((ofstream *)&cout, mol->MDSteps-1, mol->MDSteps, (ofstream *)&cout); 582 break; 583 case 'g': 584 { 585 char filename[255]; 586 cout << "Please enter filename: " << endl; 587 cin >> filename; 588 cout << Verbose(1) << "Storing temperatures in " << filename << "." << endl; 589 ofstream *output = new ofstream(filename, ios::trunc); 590 if (!mol->OutputTemperatureFromTrajectories((ofstream *)&cout, 0, mol->MDSteps, output)) 591 cout << Verbose(2) << "File could not be written." << endl; 592 else 593 cout << Verbose(2) << "File stored." << endl; 594 output->close(); 595 delete(output); 596 } 597 break; 598 } 599 599 }; 600 600 … … 605 605 static void FragmentAtoms(molecule *mol, config *configuration) 606 606 { 607 608 609 610 611 612 613 if (mol->first->next != mol->last) {// there are bonds614 615 616 617 618 619 607 int Order1; 608 clock_t start, end; 609 610 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl; 611 cout << Verbose(0) << "What's the desired bond order: "; 612 cin >> Order1; 613 if (mol->first->next != mol->last) { // there are bonds 614 start = clock(); 615 mol->FragmentMolecule((ofstream *)&cout, Order1, configuration); 616 end = clock(); 617 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl; 618 } else 619 cout << Verbose(0) << "Connection matrix has not yet been generated!" << endl; 620 620 }; 621 621 … … 1120 1120 static void testroutine(MoleculeListClass *molecules) 1121 1121 { 1122 1123 1122 // the current test routine checks the functionality of the KeySet&Graph concept: 1123 // We want to have a multiindex (the KeySet) describing a unique subgraph 1124 1124 int i, comp, counter=0; 1125 1125 … … 1134 1134 atom *Walker = mol->start; 1135 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 while (A !=Subgraphs.end()) {1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1136 // generate some KeySets 1137 cout << "Generating KeySets." << endl; 1138 KeySet TestSets[mol->AtomCount+1]; 1139 i=1; 1140 while (Walker->next != mol->end) { 1141 Walker = Walker->next; 1142 for (int j=0;j<i;j++) { 1143 TestSets[j].insert(Walker->nr); 1144 } 1145 i++; 1146 } 1147 cout << "Testing insertion of already present item in KeySets." << endl; 1148 KeySetTestPair test; 1149 test = TestSets[mol->AtomCount-1].insert(Walker->nr); 1150 if (test.second) { 1151 cout << Verbose(1) << "Insertion worked?!" << endl; 1152 } else { 1153 cout << Verbose(1) << "Insertion rejected: Present object is " << (*test.first) << "." << endl; 1154 } 1155 TestSets[mol->AtomCount].insert(mol->end->previous->nr); 1156 TestSets[mol->AtomCount].insert(mol->end->previous->previous->previous->nr); 1157 1158 // constructing Graph structure 1159 cout << "Generating Subgraph class." << endl; 1160 Graph Subgraphs; 1161 1162 // insert KeySets into Subgraphs 1163 cout << "Inserting KeySets into Subgraph class." << endl; 1164 for (int j=0;j<mol->AtomCount;j++) { 1165 Subgraphs.insert(GraphPair (TestSets[j],pair<int, double>(counter++, 1.))); 1166 } 1167 cout << "Testing insertion of already present item in Subgraph." << endl; 1168 GraphTestPair test2; 1169 test2 = Subgraphs.insert(GraphPair (TestSets[mol->AtomCount],pair<int, double>(counter++, 1.))); 1170 if (test2.second) { 1171 cout << Verbose(1) << "Insertion worked?!" << endl; 1172 } else { 1173 cout << Verbose(1) << "Insertion rejected: Present object is " << (*(test2.first)).second.first << "." << endl; 1174 } 1175 1176 // show graphs 1177 cout << "Showing Subgraph's contents, checking that it's sorted." << endl; 1178 Graph::iterator A = Subgraphs.begin(); 1179 while (A != Subgraphs.end()) { 1180 cout << (*A).second.first << ": "; 1181 KeySet::iterator key = (*A).first.begin(); 1182 comp = -1; 1183 while (key != (*A).first.end()) { 1184 if ((*key) > comp) 1185 cout << (*key) << " "; 1186 else 1187 cout << (*key) << "! "; 1188 comp = (*key); 1189 key++; 1190 } 1191 cout << endl; 1192 A++; 1193 } 1194 delete(mol); 1195 1195 }; 1196 1196 … … 1203 1203 static void SaveConfig(char *ConfigFileName, config *configuration, periodentafel *periode, MoleculeListClass *molecules) 1204 1204 { 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1205 char filename[MAXSTRINGSIZE]; 1206 ofstream output; 1207 molecule *mol = new molecule(periode); 1208 1209 // translate each to its center and merge all molecules in MoleculeListClass into this molecule 1210 int N = molecules->ListOfMolecules.size(); 1211 int *src = new int(N); 1212 N=0; 1213 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) { 1214 src[N++] = (*ListRunner)->IndexNr; 1215 (*ListRunner)->Translate(&(*ListRunner)->Center); 1216 } 1217 molecules->SimpleMultiAdd(mol, src, N); 1218 delete[](src); 1219 // ... and translate back 1220 1220 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) { 1221 1221 (*ListRunner)->Center.Scale(-1.); … … 1224 1224 } 1225 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 1226 cout << Verbose(0) << "Storing configuration ... " << endl; 1227 // get correct valence orbitals 1228 mol->CalculateOrbitals(*configuration); 1229 configuration->InitMaxMinStopStep = configuration->MaxMinStopStep = configuration->MaxPsiDouble; 1230 if (ConfigFileName != NULL) { // test the file name 1231 strcpy(filename, ConfigFileName); 1232 output.open(filename, ios::trunc); 1233 } else if (strlen(configuration->configname) != 0) { 1234 strcpy(filename, configuration->configname); 1235 output.open(configuration->configname, ios::trunc); 1236 } else { 1237 strcpy(filename, DEFAULTCONFIG); 1238 output.open(DEFAULTCONFIG, ios::trunc); 1239 } 1240 output.close(); 1241 output.clear(); 1242 cout << Verbose(0) << "Saving of config file "; 1243 if (configuration->Save(filename, periode, mol)) 1244 cout << "successful." << endl; 1245 else 1246 cout << "failed." << endl; 1247 1248 // and save to xyz file 1249 if (ConfigFileName != NULL) { 1250 strcpy(filename, ConfigFileName); 1251 strcat(filename, ".xyz"); 1252 output.open(filename, ios::trunc); 1253 } 1254 if (output == NULL) { 1255 strcpy(filename,"main_pcp_linux"); 1256 strcat(filename, ".xyz"); 1257 output.open(filename, ios::trunc); 1258 } 1259 cout << Verbose(0) << "Saving of XYZ file "; 1260 if (mol->MDSteps <= 1) { 1261 if (mol->OutputXYZ(&output)) 1262 cout << "successful." << endl; 1263 else 1264 cout << "failed." << endl; 1265 } else { 1266 if (mol->OutputTrajectoriesXYZ(&output)) 1267 cout << "successful." << endl; 1268 else 1269 cout << "failed." << endl; 1270 } 1271 output.close(); 1272 output.clear(); 1273 1274 // and save as MPQC configuration 1275 if (ConfigFileName != NULL) 1276 strcpy(filename, ConfigFileName); 1277 if (output == NULL) 1278 strcpy(filename,"main_pcp_linux"); 1279 cout << Verbose(0) << "Saving as mpqc input "; 1280 if (configuration->SaveMPQC(filename, mol)) 1281 cout << "done." << endl; 1282 else 1283 cout << "failed." << endl; 1284 1285 if (!strcmp(configuration->configpath, configuration->GetDefaultPath())) { 1286 cerr << "WARNING: config is found under different path then stated in config file::defaultpath!" << endl; 1287 } 1288 delete(mol); 1289 1289 }; 1290 1290 … … 1301 1301 static int ParseCommandLineOptions(int argc, char **argv, MoleculeListClass *&molecules, periodentafel *&periode, config& configuration, char *ConfigFileName, char *&PathToDatabases) 1302 1302 { 1303 Vector x,y,z,n;// coordinates for absolute point in cell volume1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1303 Vector x,y,z,n; // coordinates for absolute point in cell volume 1304 double *factor; // unit factor if desired 1305 ifstream test; 1306 ofstream output; 1307 string line; 1308 atom *first; 1309 bool SaveFlag = false; 1310 int ExitFlag = 0; 1311 int j; 1312 double volume = 0.; 1313 enum ConfigStatus config_present = absent; 1314 clock_t start,end; 1315 int argptr; 1316 PathToDatabases = LocalPath; 1317 1318 // simply create a new molecule, wherein the config file is loaded and the manipulation takes place 1319 molecule *mol = new molecule(periode); 1320 1320 mol->ActiveFlag = true; 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 default:// no match? Step on1388 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 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 mol->AddAtom(first);// add to molecule1481 1482 1483 1484 1485 1486 1487 1488 default:// no match? Don't step on (this is done in next switch's default)1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 MoleculeLeafClass *Subgraphs = NULL;// list of subgraphs from DFS analysis1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 Subgraphs->next->FillBondStructureFromReference((ofstream *)&cout, mol, (FragmentCounter = 0), ListOfLocalAtoms, false);// we want to keep the created ListOfLocalAtoms1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 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 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 LinkedCell LCList(mol, atof(argv[argptr]));// \NOTE not twice the radius??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 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 // 1784 // 1785 // 1786 // 1787 // 1788 // 1789 PrepareClustersinWater((ofstream *)&cout, &configuration, mol, volume, density);// if volume == 0, will calculate from ConvexEnvelope1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 mol->CountAtoms((ofstream *)&cout);// recount atoms1809 if (mol->AtomCount != 0) {// if there is more than none1810 count = mol->AtomCount;// is changed becausing of adding, thus has to be stored away beforehand1811 1812 1813 1814 1815 while (first->next != mol->end) {// make a list of all atoms with coordinates and element1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 for (int i=1;i<faktor;i++) {// then add this list with respective translation factor times1827 1828 1829 1830 first->x.CopyVector(vectors[k]);// use coordinate of original atom1831 first->x.AddVector(&x);// translate the coordinates1832 first->type = Elements[k];// insert original element1833 mol->AddAtom(first);// and add to the molecule (which increments ElementsInMolecule, AtomCount, ...)1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 default:// no match? Step on1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 } else {// no arguments, hence scan the elements db1867 1868 1869 1870 1871 1872 1873 1321 molecules->insert(mol); 1322 1323 if (argc > 1) { // config file specified as option 1324 // 1. : Parse options that just set variables or print help 1325 argptr = 1; 1326 do { 1327 if (argv[argptr][0] == '-') { 1328 cout << Verbose(0) << "Recognized command line argument: " << argv[argptr][1] << ".\n"; 1329 argptr++; 1330 switch(argv[argptr-1][1]) { 1331 case 'h': 1332 case 'H': 1333 case '?': 1334 cout << "MoleCuilder suite" << endl << "==================" << endl << endl; 1335 cout << "Usage: " << argv[0] << "[config file] [-{acefpsthH?vfrp}] [further arguments]" << endl; 1336 cout << "or simply " << argv[0] << " without arguments for interactive session." << endl; 1337 cout << "\t-a Z x1 x2 x3\tAdd new atom of element Z at coordinates (x1,x2,x3)." << endl; 1338 cout << "\t-A <source>\tCreate adjacency list from bonds parsed from 'dbond'-style file." <<endl; 1339 cout << "\t-b x1 x2 x3\tCenter atoms in domain with given edge lengths of (x1,x2,x3)." << endl; 1340 cout << "\t-B <basis>\tSetting basis to store to MPQC config files." << endl; 1341 cout << "\t-c x1 x2 x3\tCenter atoms in domain with a minimum distance to boundary of (x1,x2,x3)." << endl; 1342 cout << "\t-D <bond distance>\tDepth-First-Search Analysis of the molecule, giving cycles and tree/back edges." << endl; 1343 cout << "\t-O\tCenter atoms in origin." << endl; 1344 cout << "\t-d x1 x2 x3\tDuplicate cell along each axis by given factor." << endl; 1345 cout << "\t-e <file>\tSets the databases path to be parsed (default: ./)." << endl; 1346 cout << "\t-E <id> <Z>\tChange atom <id>'s element to <Z>, <id> begins at 0." << endl; 1347 cout << "\t-f/F <dist> <order>\tFragments the molecule in BOSSANOVA manner (with/out rings compressed) and stores config files in same dir as config (return code 0 - fragmented, 2 - no fragmentation necessary)." << endl; 1348 cout << "\t-h/-H/-?\tGive this help screen." << endl; 1349 cout << "\t-m <0/1>\tCalculate (0)/ Align in(1) PAS with greatest EV along z axis." << endl; 1350 cout << "\t-n\tFast parsing (i.e. no trajectories are looked for)." << endl; 1351 cout << "\t-N\tGet non-convex-envelope." << endl; 1352 cout << "\t-o <out>\tGet volume of the convex envelope (and store to tecplot file)." << endl; 1353 cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl; 1354 cout << "\t-P <file>\tParse given forces file and append as an MD step to config file via Verlet." << endl; 1355 cout << "\t-r\t\tConvert file from an old pcp syntax." << endl; 1356 cout << "\t-t x1 x2 x3\tTranslate all atoms by this vector (x1,x2,x3)." << endl; 1357 cout << "\t-T <file> Store temperatures from the config file in <file>." << endl; 1358 cout << "\t-s x1 x2 x3\tScale all atom coordinates by this vector (x1,x2,x3)." << endl; 1359 cout << "\t-u rho\tsuspend in water solution and output necessary cell lengths, average density rho and repetition." << endl; 1360 cout << "\t-v/-V\t\tGives version information." << endl; 1361 cout << "Note: config files must not begin with '-' !" << endl; 1362 delete(mol); 1363 delete(periode); 1364 return (1); 1365 break; 1366 case 'v': 1367 case 'V': 1368 cout << argv[0] << " " << VERSIONSTRING << endl; 1369 cout << "Build your own molecule position set." << endl; 1370 delete(mol); 1371 delete(periode); 1372 return (1); 1373 break; 1374 case 'e': 1375 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1376 cerr << "Not enough or invalid arguments for specifying element db: -e <db file>" << endl; 1377 } else { 1378 cout << "Using " << argv[argptr] << " as elements database." << endl; 1379 PathToDatabases = argv[argptr]; 1380 argptr+=1; 1381 } 1382 break; 1383 case 'n': 1384 cout << "I won't parse trajectories." << endl; 1385 configuration.FastParsing = true; 1386 break; 1387 default: // no match? Step on 1388 argptr++; 1389 break; 1390 } 1391 } else 1392 argptr++; 1393 } while (argptr < argc); 1394 1395 // 2. Parse the element database 1396 if (periode->LoadPeriodentafel(PathToDatabases)) { 1397 cout << Verbose(0) << "Element list loaded successfully." << endl; 1398 //periode->Output((ofstream *)&cout); 1399 } else { 1400 cout << Verbose(0) << "Element list loading failed." << endl; 1401 return 1; 1402 } 1403 // 3. Find config file name and parse if possible 1404 if (argv[1][0] != '-') { 1405 cout << Verbose(0) << "Config file given." << endl; 1406 test.open(argv[1], ios::in); 1407 if (test == NULL) { 1408 //return (1); 1409 output.open(argv[1], ios::out); 1410 if (output == NULL) { 1411 cout << Verbose(1) << "Specified config file " << argv[1] << " not found." << endl; 1412 config_present = absent; 1413 } else { 1414 cout << "Empty configuration file." << endl; 1415 strcpy(ConfigFileName, argv[1]); 1416 config_present = empty; 1417 output.close(); 1418 } 1419 } else { 1420 test.close(); 1421 strcpy(ConfigFileName, argv[1]); 1422 cout << Verbose(1) << "Specified config file found, parsing ... "; 1423 switch (configuration.TestSyntax(ConfigFileName, periode, mol)) { 1424 case 1: 1425 cout << "new syntax." << endl; 1426 configuration.Load(ConfigFileName, periode, mol); 1427 config_present = present; 1428 break; 1429 case 0: 1430 cout << "old syntax." << endl; 1431 configuration.LoadOld(ConfigFileName, periode, mol); 1432 config_present = present; 1433 break; 1434 default: 1435 cout << "Unknown syntax or empty, yet present file." << endl; 1436 config_present = empty; 1437 } 1438 } 1439 } else 1440 config_present = absent; 1441 // 4. parse again through options, now for those depending on elements db and config presence 1442 argptr = 1; 1443 do { 1444 cout << "Current Command line argument: " << argv[argptr] << "." << endl; 1445 if (argv[argptr][0] == '-') { 1446 argptr++; 1447 if ((config_present == present) || (config_present == empty)) { 1448 switch(argv[argptr-1][1]) { 1449 case 'p': 1450 ExitFlag = 1; 1451 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1452 ExitFlag = 255; 1453 cerr << "Not enough arguments for parsing: -p <xyz file>" << endl; 1454 } else { 1455 SaveFlag = true; 1456 cout << Verbose(1) << "Parsing xyz file for new atoms." << endl; 1457 if (!mol->AddXYZFile(argv[argptr])) 1458 cout << Verbose(2) << "File not found." << endl; 1459 else { 1460 cout << Verbose(2) << "File found and parsed." << endl; 1461 config_present = present; 1462 } 1463 } 1464 break; 1465 case 'a': 1466 ExitFlag = 1; 1467 if ((argptr >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr+1]))) { 1468 ExitFlag = 255; 1469 cerr << "Not enough or invalid arguments for adding atom: -a <element> <x> <y> <z>" << endl; 1470 } else { 1471 SaveFlag = true; 1472 cout << Verbose(1) << "Adding new atom with element " << argv[argptr] << " at (" << argv[argptr+1] << "," << argv[argptr+2] << "," << argv[argptr+3] << "), "; 1473 first = new atom; 1474 first->type = periode->FindElement(atoi(argv[argptr])); 1475 if (first->type != NULL) 1476 cout << Verbose(2) << "found element " << first->type->name << endl; 1477 for (int i=NDIM;i--;) 1478 first->x.x[i] = atof(argv[argptr+1+i]); 1479 if (first->type != NULL) { 1480 mol->AddAtom(first); // add to molecule 1481 if ((config_present == empty) && (mol->AtomCount != 0)) 1482 config_present = present; 1483 } else 1484 cerr << Verbose(1) << "Could not find the specified element." << endl; 1485 argptr+=4; 1486 } 1487 break; 1488 default: // no match? Don't step on (this is done in next switch's default) 1489 break; 1490 } 1491 } 1492 if (config_present == present) { 1493 switch(argv[argptr-1][1]) { 1494 case 'B': 1495 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1496 ExitFlag = 255; 1497 cerr << "Not enough or invalid arguments given for setting MPQC basis: -B <basis name>" << endl; 1498 } else { 1499 configuration.basis = argv[argptr]; 1500 cout << Verbose(1) << "Setting MPQC basis to " << configuration.basis << "." << endl; 1501 argptr+=1; 1502 } 1503 break; 1504 case 'D': 1505 ExitFlag = 1; 1506 { 1507 cout << Verbose(1) << "Depth-First-Search Analysis." << endl; 1508 MoleculeLeafClass *Subgraphs = NULL; // list of subgraphs from DFS analysis 1509 int *MinimumRingSize = new int[mol->AtomCount]; 1510 atom ***ListOfLocalAtoms = NULL; 1511 int FragmentCounter = 0; 1512 class StackClass<bond *> *BackEdgeStack = NULL; 1513 class StackClass<bond *> *LocalBackEdgeStack = NULL; 1514 mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr]), configuration.GetIsAngstroem()); 1515 mol->CreateListOfBondsPerAtom((ofstream *)&cout); 1516 Subgraphs = mol->DepthFirstSearchAnalysis((ofstream *)&cout, BackEdgeStack); 1517 if (Subgraphs != NULL) { 1518 Subgraphs->next->FillBondStructureFromReference((ofstream *)&cout, mol, (FragmentCounter = 0), ListOfLocalAtoms, false); // we want to keep the created ListOfLocalAtoms 1519 while (Subgraphs->next != NULL) { 1520 Subgraphs = Subgraphs->next; 1521 LocalBackEdgeStack = new StackClass<bond *> (Subgraphs->Leaf->BondCount); 1522 Subgraphs->Leaf->PickLocalBackEdges((ofstream *)&cout, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack); 1523 Subgraphs->Leaf->CyclicStructureAnalysis((ofstream *)&cout, BackEdgeStack, MinimumRingSize); 1524 delete(LocalBackEdgeStack); 1525 delete(Subgraphs->previous); 1526 } 1527 delete(Subgraphs); 1528 for (int i=0;i<FragmentCounter;i++) 1529 Free((void **)&ListOfLocalAtoms[FragmentCounter], "ParseCommandLineOptions: **ListOfLocalAtoms[]"); 1530 Free((void **)&ListOfLocalAtoms, "ParseCommandLineOptions: ***ListOfLocalAtoms"); 1531 } 1532 delete(BackEdgeStack); 1533 delete[](MinimumRingSize); 1534 } 1535 //argptr+=1; 1536 break; 1537 case 'E': 1538 ExitFlag = 1; 1539 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (argv[argptr+1][0] == '-')) { 1540 ExitFlag = 255; 1541 cerr << "Not enough or invalid arguments given for changing element: -E <atom nr.> <element>" << endl; 1542 } else { 1543 SaveFlag = true; 1544 cout << Verbose(1) << "Changing atom " << argv[argptr] << " to element " << argv[argptr+1] << "." << endl; 1545 first = mol->FindAtom(atoi(argv[argptr])); 1546 first->type = periode->FindElement(atoi(argv[argptr+1])); 1547 argptr+=2; 1548 } 1549 break; 1550 case 'A': 1551 ExitFlag = 1; 1552 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1553 ExitFlag =255; 1554 cerr << "Missing source file for bonds in molecule: -A <bond sourcefile>" << endl; 1555 } else { 1556 cout << "Parsing bonds from " << argv[argptr] << "." << endl; 1557 ifstream *input = new ifstream(argv[argptr]); 1558 mol->CreateAdjacencyList2((ofstream *)&cout, input); 1559 input->close(); 1560 argptr+=1; 1561 } 1562 break; 1563 case 'N': 1564 ExitFlag = 1; 1565 if ((argptr+1 >= argc) || (argv[argptr+1][0] == '-')){ 1566 ExitFlag = 255; 1567 cerr << "Not enough or invalid arguments given for non-convex envelope: -o <radius> <tecplot output file>" << endl; 1568 } else { 1569 class Tesselation T; 1570 int N = 15; 1571 int number = 100; 1572 string filename(argv[argptr+1]); 1573 filename.append(".csv"); 1574 cout << Verbose(0) << "Evaluating non-convex envelope."; 1575 cout << Verbose(1) << "Using rolling ball of radius " << atof(argv[argptr]) << " and storing tecplot data in " << argv[argptr+1] << "." << endl; 1576 LinkedCell LCList(mol, atof(argv[argptr])); // \NOTE not twice the radius?? 1577 Find_non_convex_border((ofstream *)&cout, mol, &T, &LCList, argv[argptr+1], atof(argv[argptr])); 1578 FindDistributionOfEllipsoids((ofstream *)&cout, &T, &LCList, N, number, filename.c_str()); 1579 argptr+=2; 1580 } 1581 break; 1582 case 'T': 1583 ExitFlag = 1; 1584 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1585 ExitFlag = 255; 1586 cerr << "Not enough or invalid arguments given for storing tempature: -T <temperature file>" << endl; 1587 } else { 1588 cout << Verbose(1) << "Storing temperatures in " << argv[argptr] << "." << endl; 1589 ofstream *output = new ofstream(argv[argptr], ios::trunc); 1590 if (!mol->OutputTemperatureFromTrajectories((ofstream *)&cout, 0, mol->MDSteps, output)) 1591 cout << Verbose(2) << "File could not be written." << endl; 1592 else 1593 cout << Verbose(2) << "File stored." << endl; 1594 output->close(); 1595 delete(output); 1596 argptr+=1; 1597 } 1598 break; 1599 case 'P': 1600 ExitFlag = 1; 1601 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1602 ExitFlag = 255; 1603 cerr << "Not enough or invalid arguments given for parsing and integrating forces: -P <forces file>" << endl; 1604 } else { 1605 SaveFlag = true; 1606 cout << Verbose(1) << "Parsing forces file and Verlet integrating." << endl; 1607 if (!mol->VerletForceIntegration(argv[argptr], configuration.Deltat, configuration.GetIsAngstroem())) 1608 cout << Verbose(2) << "File not found." << endl; 1609 else 1610 cout << Verbose(2) << "File found and parsed." << endl; 1611 argptr+=1; 1612 } 1613 break; 1614 case 't': 1615 ExitFlag = 1; 1616 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) { 1617 ExitFlag = 255; 1618 cerr << "Not enough or invalid arguments given for translation: -t <x> <y> <z>" << endl; 1619 } else { 1620 ExitFlag = 1; 1621 SaveFlag = true; 1622 cout << Verbose(1) << "Translating all ions to new origin." << endl; 1623 for (int i=NDIM;i--;) 1624 x.x[i] = atof(argv[argptr+i]); 1625 mol->Translate((const Vector *)&x); 1626 argptr+=3; 1627 } 1628 break; 1629 case 's': 1630 ExitFlag = 1; 1631 if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) { 1632 ExitFlag = 255; 1633 cerr << "Not enough or invalid arguments given for scaling: -s <factor/[factor_x]> [factor_y] [factor_z]" << endl; 1634 } else { 1635 SaveFlag = true; 1636 j = -1; 1637 cout << Verbose(1) << "Scaling all ion positions by factor." << endl; 1638 factor = new double[NDIM]; 1639 factor[0] = atof(argv[argptr]); 1640 if ((argptr < argc) && (IsValidNumber(argv[argptr]))) 1641 argptr++; 1642 factor[1] = atof(argv[argptr]); 1643 if ((argptr < argc) && (IsValidNumber(argv[argptr]))) 1644 argptr++; 1645 factor[2] = atof(argv[argptr]); 1646 mol->Scale(&factor); 1647 for (int i=0;i<NDIM;i++) { 1648 j += i+1; 1649 x.x[i] = atof(argv[NDIM+i]); 1650 mol->cell_size[j]*=factor[i]; 1651 } 1652 delete[](factor); 1653 argptr+=1; 1654 } 1655 break; 1656 case 'b': 1657 ExitFlag = 1; 1658 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) { 1659 ExitFlag = 255; 1660 cerr << "Not enough or invalid arguments given for centering in box: -b <length_x> <length_y> <length_z>" << endl; 1661 } else { 1662 SaveFlag = true; 1663 j = -1; 1664 cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl; 1665 j=-1; 1666 for (int i=0;i<NDIM;i++) { 1667 j += i+1; 1668 x.x[i] = atof(argv[argptr++]); 1669 mol->cell_size[j] += x.x[i]*2.; 1670 } 1671 // center 1672 mol->CenterInBox((ofstream *)&cout, &x); 1673 // update Box of atoms by boundary 1674 mol->SetBoxDimension(&x); 1675 } 1676 break; 1677 case 'c': 1678 ExitFlag = 1; 1679 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) { 1680 ExitFlag = 255; 1681 cerr << "Not enough or invalid arguments given for centering with boundary: -c <boundary_x> <boundary_y> <boundary_z>" << endl; 1682 } else { 1683 SaveFlag = true; 1684 j = -1; 1685 cout << Verbose(1) << "Centering atoms in config file within given additional boundary." << endl; 1686 // make every coordinate positive 1687 mol->CenterEdge((ofstream *)&cout, &x); 1688 // update Box of atoms by boundary 1689 mol->SetBoxDimension(&x); 1690 // translate each coordinate by boundary 1691 j=-1; 1692 for (int i=0;i<NDIM;i++) { 1693 j += i+1; 1694 x.x[i] = atof(argv[argptr++]); 1695 mol->cell_size[j] += x.x[i]*2.; 1696 } 1697 mol->Translate((const Vector *)&x); 1698 } 1699 break; 1700 case 'O': 1701 ExitFlag = 1; 1702 SaveFlag = true; 1703 cout << Verbose(1) << "Centering atoms on edge and setting box dimensions." << endl; 1704 mol->CenterEdge((ofstream *)&cout, &x); 1705 mol->SetBoxDimension(&x); 1706 break; 1707 case 'r': 1708 ExitFlag = 1; 1709 SaveFlag = true; 1710 cout << Verbose(1) << "Converting config file from supposed old to new syntax." << endl; 1711 break; 1712 case 'F': 1713 case 'f': 1714 ExitFlag = 1; 1715 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1]))) { 1716 ExitFlag = 255; 1717 cerr << "Not enough or invalid arguments for fragmentation: -f <max. bond distance> <bond order>" << endl; 1718 } else { 1719 cout << "Fragmenting molecule with bond distance " << argv[argptr] << " angstroem, order of " << argv[argptr+1] << "." << endl; 1720 cout << Verbose(0) << "Creating connection matrix..." << endl; 1721 start = clock(); 1722 mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr++]), configuration.GetIsAngstroem()); 1723 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl; 1724 if (mol->first->next != mol->last) { 1725 ExitFlag = mol->FragmentMolecule((ofstream *)&cout, atoi(argv[argptr]), &configuration); 1726 } 1727 end = clock(); 1728 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl; 1729 argptr+=2; 1730 } 1731 break; 1732 case 'm': 1733 ExitFlag = 1; 1734 j = atoi(argv[argptr++]); 1735 if ((j<0) || (j>1)) { 1736 cerr << Verbose(1) << "ERROR: Argument of '-m' should be either 0 for no-rotate or 1 for rotate." << endl; 1737 j = 0; 1738 } 1739 if (j) { 1740 SaveFlag = true; 1741 cout << Verbose(0) << "Converting to prinicipal axis system." << endl; 1742 } else 1743 cout << Verbose(0) << "Evaluating prinicipal axis." << endl; 1744 mol->PrincipalAxisSystem((ofstream *)&cout, (bool)j); 1745 break; 1746 case 'o': 1747 ExitFlag = 1; 1748 if ((argptr >= argc) || (argv[argptr][0] == '-')){ 1749 ExitFlag = 255; 1750 cerr << "Not enough or invalid arguments given for convex envelope: -o <tecplot output file>" << endl; 1751 } else { 1752 cout << Verbose(0) << "Evaluating volume of the convex envelope."; 1753 cout << Verbose(1) << "Storing tecplot data in " << argv[argptr] << "." << endl; 1754 VolumeOfConvexEnvelope((ofstream *)&cout, argv[argptr], &configuration, NULL, mol); 1755 argptr+=1; 1756 } 1757 break; 1758 case 'U': 1759 ExitFlag = 1; 1760 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) ) { 1761 ExitFlag = 255; 1762 cerr << "Not enough or invalid arguments given for suspension with specified volume: -U <volume> <density>" << endl; 1763 volume = -1; // for case 'u': don't print error again 1764 } else { 1765 volume = atof(argv[argptr++]); 1766 cout << Verbose(0) << "Using " << volume << " angstrom^3 as the volume instead of convex envelope one's." << endl; 1767 } 1768 case 'u': 1769 ExitFlag = 1; 1770 if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) { 1771 if (volume != -1) 1772 ExitFlag = 255; 1773 cerr << "Not enough arguments given for suspension: -u <density>" << endl; 1774 } else { 1775 double density; 1776 SaveFlag = true; 1777 cout << Verbose(0) << "Evaluating necessary cell volume for a cluster suspended in water."; 1778 density = atof(argv[argptr++]); 1779 if (density < 1.0) { 1780 cerr << Verbose(0) << "Density must be greater than 1.0g/cm^3 !" << endl; 1781 density = 1.3; 1782 } 1783 // for(int i=0;i<NDIM;i++) { 1784 // repetition[i] = atoi(argv[argptr++]); 1785 // if (repetition[i] < 1) 1786 // cerr << Verbose(0) << "ERROR: repetition value must be greater 1!" << endl; 1787 // repetition[i] = 1; 1788 // } 1789 PrepareClustersinWater((ofstream *)&cout, &configuration, mol, volume, density); // if volume == 0, will calculate from ConvexEnvelope 1790 } 1791 break; 1792 case 'd': 1793 ExitFlag = 1; 1794 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) { 1795 ExitFlag = 255; 1796 cerr << "Not enough or invalid arguments given for repeating cells: -d <repeat_x> <repeat_y> <repeat_z>" << endl; 1797 } else { 1798 SaveFlag = true; 1799 for (int axis = 1; axis <= NDIM; axis++) { 1800 int faktor = atoi(argv[argptr++]); 1801 int count; 1802 element ** Elements; 1803 Vector ** vectors; 1804 if (faktor < 1) { 1805 cerr << Verbose(0) << "ERROR: Repetition faktor mus be greater than 1!" << endl; 1806 faktor = 1; 1807 } 1808 mol->CountAtoms((ofstream *)&cout); // recount atoms 1809 if (mol->AtomCount != 0) { // if there is more than none 1810 count = mol->AtomCount; // is changed becausing of adding, thus has to be stored away beforehand 1811 Elements = new element *[count]; 1812 vectors = new Vector *[count]; 1813 j = 0; 1814 first = mol->start; 1815 while (first->next != mol->end) { // make a list of all atoms with coordinates and element 1816 first = first->next; 1817 Elements[j] = first->type; 1818 vectors[j] = &first->x; 1819 j++; 1820 } 1821 if (count != j) 1822 cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl; 1823 x.Zero(); 1824 y.Zero(); 1825 y.x[abs(axis)-1] = mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] * abs(axis)/axis; // last term is for sign, first is for magnitude 1826 for (int i=1;i<faktor;i++) { // then add this list with respective translation factor times 1827 x.AddVector(&y); // per factor one cell width further 1828 for (int k=count;k--;) { // go through every atom of the original cell 1829 first = new atom(); // create a new body 1830 first->x.CopyVector(vectors[k]); // use coordinate of original atom 1831 first->x.AddVector(&x); // translate the coordinates 1832 first->type = Elements[k]; // insert original element 1833 mol->AddAtom(first); // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...) 1834 } 1835 } 1836 // free memory 1837 delete[](Elements); 1838 delete[](vectors); 1839 // correct cell size 1840 if (axis < 0) { // if sign was negative, we have to translate everything 1841 x.Zero(); 1842 x.AddVector(&y); 1843 x.Scale(-(faktor-1)); 1844 mol->Translate(&x); 1845 } 1846 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor; 1847 } 1848 } 1849 } 1850 break; 1851 default: // no match? Step on 1852 if ((argptr < argc) && (argv[argptr][0] != '-')) // if it started with a '-' we've already made a step! 1853 argptr++; 1854 break; 1855 } 1856 } 1857 } else argptr++; 1858 } while (argptr < argc); 1859 if (SaveFlag) 1860 SaveConfig(ConfigFileName, &configuration, periode, molecules); 1861 if ((ExitFlag >= 1)) { 1862 delete(mol); 1863 delete(periode); 1864 return (ExitFlag); 1865 } 1866 } else { // no arguments, hence scan the elements db 1867 if (periode->LoadPeriodentafel(PathToDatabases)) 1868 cout << Verbose(0) << "Element list loaded successfully." << endl; 1869 else 1870 cout << Verbose(0) << "Element list loading failed." << endl; 1871 configuration.RetrieveConfigPathAndName("main_pcp_linux"); 1872 } 1873 return(0); 1874 1874 }; 1875 1875 … … 1878 1878 int main(int argc, char **argv) 1879 1879 { 1880 1881 1882 1883 1884 char choice;// menu choice char1885 Vector x,y,z,n;// coordinates for absolute point in cell volume1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 if (j) return j;// something went wrong1898 1899 1900 1880 periodentafel *periode = new periodentafel; // and a period table of all elements 1881 MoleculeListClass *molecules = new MoleculeListClass; // list of all molecules 1882 molecule *mol = NULL; 1883 config configuration; 1884 char choice; // menu choice char 1885 Vector x,y,z,n; // coordinates for absolute point in cell volume 1886 ifstream test; 1887 ofstream output; 1888 string line; 1889 char ConfigFileName[MAXSTRINGSIZE]; 1890 char *ElementsFileName = NULL; 1891 int j; 1892 1893 // =========================== PARSE COMMAND LINE OPTIONS ==================================== 1894 ConfigFileName[0] = '\0'; 1895 j = ParseCommandLineOptions(argc, argv, molecules, periode, configuration, ConfigFileName, ElementsFileName); 1896 if (j == 1) return 0; // just for -v and -h options 1897 if (j) return j; // something went wrong 1898 1899 // General stuff 1900 if (molecules->ListOfMolecules.size() == 0) { 1901 1901 mol = new molecule(periode); 1902 1902 if (mol->cell_size[0] == 0.) { … … 1908 1908 } 1909 1909 molecules->insert(mol); 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1910 } 1911 if (strlen(ConfigFileName) == 0) 1912 strcpy(ConfigFileName, DEFAULTCONFIG); 1913 1914 1915 // =========================== START INTERACTIVE SESSION ==================================== 1916 1917 // now the main construction loop 1918 cout << Verbose(0) << endl << "Now comes the real construction..." << endl; 1919 do { 1920 cout << Verbose(0) << endl << endl; 1921 cout << Verbose(0) << "============Molecule list=======================" << endl; 1922 molecules->Enumerate((ofstream *)&cout); 1923 cout << Verbose(0) << "============Menu===============================" << endl; 1924 1924 cout << Verbose(0) << "a - set molecule (in)active" << endl; 1925 1925 cout << Verbose(0) << "e - edit molecules (load, parse, save)" << endl; … … 1937 1937 cin >> choice; 1938 1938 1939 1940 1939 switch (choice) { 1940 case 'a': // (in)activate molecule 1941 1941 { 1942 1942 cout << "Enter index of molecule: "; … … 1946 1946 (*ListRunner)->ActiveFlag = !(*ListRunner)->ActiveFlag; 1947 1947 } 1948 1949 1950 1951 1952 1948 break; 1949 1950 case 'c': // edit each field of the configuration 1951 configuration.Edit(); 1952 break; 1953 1953 1954 1954 case 'e': // create molecule … … 1968 1968 break; 1969 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1970 case 'q': // quit 1971 break; 1972 1973 case 's': // save to config file 1974 SaveConfig(ConfigFileName, &configuration, periode, molecules); 1975 break; 1976 1977 case 'T': 1978 testroutine(molecules); 1979 break; 1980 1981 default: 1982 break; 1983 }; 1984 } while (choice != 'q'); 1985 1986 // save element data base 1987 if (periode->StorePeriodentafel(ElementsFileName)) //ElementsFileName 1988 cout << Verbose(0) << "Saving of elements.db successful." << endl; 1989 else 1990 cout << Verbose(0) << "Saving of elements.db failed." << endl; 1991 1992 delete(molecules); 1993 delete(periode); 1994 return (0); 1995 1995 } 1996 1996 -
src/config.cpp
r178f92 r437922 13 13 config::config() 14 14 { 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 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; 85 85 }; 86 86 … … 90 90 config::~config() 91 91 { 92 93 94 95 96 92 Free((void **)&mainname, "config::~config: *mainname"); 93 Free((void **)&defaultpath, "config::~config: *defaultpath"); 94 Free((void **)&pseudopotpath, "config::~config: *pseudopotpath"); 95 Free((void **)&configpath, "config::~config: *configpath"); 96 Free((void **)&configname, "config::~config: *configname"); 97 97 }; 98 98 … … 103 103 void config::Edit() 104 104 { 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 105 char choice; 106 107 do { 108 cout << Verbose(0) << "===========EDIT CONFIGURATION============================" << endl; 109 cout << Verbose(0) << " A - mainname (prefix for all runtime files)" << endl; 110 cout << Verbose(0) << " B - Default path (for runtime files)" << endl; 111 cout << Verbose(0) << " C - Path of pseudopotential files" << endl; 112 cout << Verbose(0) << " D - Number of coefficient sharing processes" << endl; 113 cout << Verbose(0) << " E - Number of wave function sharing processes" << endl; 114 cout << Verbose(0) << " F - 0: Don't output density for OpenDX, 1: do" << endl; 115 cout << Verbose(0) << " G - 0: Don't output physical data, 1: do" << endl; 116 cout << Verbose(0) << " H - 0: Don't output densities of each unperturbed orbital for OpenDX, 1: do" << endl; 117 cout << Verbose(0) << " I - 0: Don't output current density for OpenDX, 1: do" << endl; 118 cout << Verbose(0) << " J - 0: Don't do the full current calculation, 1: do" << endl; 119 cout << Verbose(0) << " K - 0: Don't do perturbation calculation to obtain susceptibility and shielding, 1: do" << endl; 120 cout << Verbose(0) << " L - 0: Wannier centres as calculated, 1: common centre for all, 2: unite centres according to spread, 3: cell centre, 4: shifted to nearest grid point" << endl; 121 cout << Verbose(0) << " M - Absolute begin of unphysical sawtooth transfer for position operator within cell" << endl; 122 cout << Verbose(0) << " N - (0,1,2) x,y,z-plane to do two-dimensional current vector cut" << endl; 123 cout << Verbose(0) << " O - Absolute position along vector cut axis for cut plane" << endl; 124 cout << Verbose(0) << " P - Additional Gram-Schmidt-Orthonormalization to stabilize numerics" << endl; 125 cout << Verbose(0) << " Q - Initial integer value of random number generator" << endl; 126 cout << Verbose(0) << " R - for perturbation 0, for structure optimization defines upper limit of iterations" << endl; 127 cout << Verbose(0) << " T - Output visual after ...th step" << endl; 128 cout << Verbose(0) << " U - Output source densities of wave functions after ...th step" << endl; 129 cout << Verbose(0) << " X - minimization iterations per wave function, if unsure leave at default value 0" << endl; 130 cout << Verbose(0) << " Y - tolerance value for total spread in iterative Jacobi diagonalization" << endl; 131 cout << Verbose(0) << " Z - Maximum number of minimization iterations" << endl; 132 cout << Verbose(0) << " a - Relative change in total energy to stop min. iteration" << endl; 133 cout << Verbose(0) << " b - Relative change in kinetic energy to stop min. iteration" << endl; 134 cout << Verbose(0) << " c - Check stop conditions every ..th step during min. iteration" << endl; 135 cout << Verbose(0) << " e - Maximum number of minimization iterations during initial level" << endl; 136 cout << Verbose(0) << " f - Relative change in total energy to stop min. iteration during initial level" << endl; 137 cout << Verbose(0) << " g - Relative change in kinetic energy to stop min. iteration during initial level" << endl; 138 cout << Verbose(0) << " h - Check stop conditions every ..th step during min. iteration during initial level" << endl; 139 // cout << Verbose(0) << " j - six lower diagonal entries of matrix, defining the unit cell" << endl; 140 cout << Verbose(0) << " k - Energy cutoff of plane wave basis in Hartree" << endl; 141 cout << Verbose(0) << " l - Maximum number of levels in multi-level-ansatz" << endl; 142 cout << Verbose(0) << " m - Factor by which grid nodes increase between standard and upper level" << endl; 143 cout << Verbose(0) << " n - 0: Don't use RiemannTensor, 1: Do" << endl; 144 cout << Verbose(0) << " o - Factor by which grid nodes increase between Riemann and standard(?) level" << endl; 145 cout << Verbose(0) << " p - Number of Riemann levels" << endl; 146 cout << Verbose(0) << " r - 0: Don't Use RiemannTensor, 1: Do" << endl; 147 cout << Verbose(0) << " s - 0: Doubly occupied orbitals, 1: Up-/Down-Orbitals" << endl; 148 cout << Verbose(0) << " t - Number of orbitals (depends pn SpinType)" << endl; 149 cout << Verbose(0) << " u - Number of SpinUp orbitals (depends on SpinType)" << endl; 150 cout << Verbose(0) << " v - Number of SpinDown orbitals (depends on SpinType)" << endl; 151 cout << Verbose(0) << " w - Number of additional, unoccupied orbitals" << endl; 152 cout << Verbose(0) << " x - radial cutoff for ewald summation in Bohrradii" << endl; 153 cout << Verbose(0) << " y - 0: Don't do structure optimization beforehand, 1: Do" << endl; 154 cout << Verbose(0) << " z - 0: Units are in Bohr radii, 1: units are in Aengstrom" << endl; 155 cout << Verbose(0) << " i - 0: Coordinates given in file are absolute, 1: ... are relative to unit cell" << endl; 156 cout << Verbose(0) << "=========================================================" << endl; 157 cout << Verbose(0) << "INPUT: "; 158 cin >> choice; 159 160 switch (choice) { 161 case 'A': // mainname 162 cout << Verbose(0) << "Old: " << config::mainname << "\t new: "; 163 cin >> config::mainname; 164 break; 165 case 'B': // defaultpath 166 cout << Verbose(0) << "Old: " << config::defaultpath << "\t new: "; 167 cin >> config::defaultpath; 168 break; 169 case 'C': // pseudopotpath 170 cout << Verbose(0) << "Old: " << config::pseudopotpath << "\t new: "; 171 cin >> config::pseudopotpath; 172 break; 173 174 case 'D': // ProcPEGamma 175 cout << Verbose(0) << "Old: " << config::ProcPEGamma << "\t new: "; 176 cin >> config::ProcPEGamma; 177 break; 178 case 'E': // ProcPEPsi 179 cout << Verbose(0) << "Old: " << config::ProcPEPsi << "\t new: "; 180 cin >> config::ProcPEPsi; 181 break; 182 case 'F': // DoOutVis 183 cout << Verbose(0) << "Old: " << config::DoOutVis << "\t new: "; 184 cin >> config::DoOutVis; 185 break; 186 case 'G': // DoOutMes 187 cout << Verbose(0) << "Old: " << config::DoOutMes << "\t new: "; 188 cin >> config::DoOutMes; 189 break; 190 case 'H': // DoOutOrbitals 191 cout << Verbose(0) << "Old: " << config::DoOutOrbitals << "\t new: "; 192 cin >> config::DoOutOrbitals; 193 break; 194 case 'I': // DoOutCurrent 195 cout << Verbose(0) << "Old: " << config::DoOutCurrent << "\t new: "; 196 cin >> config::DoOutCurrent; 197 break; 198 case 'J': // DoFullCurrent 199 cout << Verbose(0) << "Old: " << config::DoFullCurrent << "\t new: "; 200 cin >> config::DoFullCurrent; 201 break; 202 case 'K': // DoPerturbation 203 cout << Verbose(0) << "Old: " << config::DoPerturbation << "\t new: "; 204 cin >> config::DoPerturbation; 205 break; 206 case 'L': // CommonWannier 207 cout << Verbose(0) << "Old: " << config::CommonWannier << "\t new: "; 208 cin >> config::CommonWannier; 209 break; 210 case 'M': // SawtoothStart 211 cout << Verbose(0) << "Old: " << config::SawtoothStart << "\t new: "; 212 cin >> config::SawtoothStart; 213 break; 214 case 'N': // VectorPlane 215 cout << Verbose(0) << "Old: " << config::VectorPlane << "\t new: "; 216 cin >> config::VectorPlane; 217 break; 218 case 'O': // VectorCut 219 cout << Verbose(0) << "Old: " << config::VectorCut << "\t new: "; 220 cin >> config::VectorCut; 221 break; 222 case 'P': // UseAddGramSch 223 cout << Verbose(0) << "Old: " << config::UseAddGramSch << "\t new: "; 224 cin >> config::UseAddGramSch; 225 break; 226 case 'Q': // Seed 227 cout << Verbose(0) << "Old: " << config::Seed << "\t new: "; 228 cin >> config::Seed; 229 break; 230 231 case 'R': // MaxOuterStep 232 cout << Verbose(0) << "Old: " << config::MaxOuterStep << "\t new: "; 233 cin >> config::MaxOuterStep; 234 break; 235 case 'T': // OutVisStep 236 cout << Verbose(0) << "Old: " << config::OutVisStep << "\t new: "; 237 cin >> config::OutVisStep; 238 break; 239 case 'U': // OutSrcStep 240 cout << Verbose(0) << "Old: " << config::OutSrcStep << "\t new: "; 241 cin >> config::OutSrcStep; 242 break; 243 case 'X': // MaxPsiStep 244 cout << Verbose(0) << "Old: " << config::MaxPsiStep << "\t new: "; 245 cin >> config::MaxPsiStep; 246 break; 247 case 'Y': // EpsWannier 248 cout << Verbose(0) << "Old: " << config::EpsWannier << "\t new: "; 249 cin >> config::EpsWannier; 250 break; 251 252 case 'Z': // MaxMinStep 253 cout << Verbose(0) << "Old: " << config::MaxMinStep << "\t new: "; 254 cin >> config::MaxMinStep; 255 break; 256 case 'a': // RelEpsTotalEnergy 257 cout << Verbose(0) << "Old: " << config::RelEpsTotalEnergy << "\t new: "; 258 cin >> config::RelEpsTotalEnergy; 259 break; 260 case 'b': // RelEpsKineticEnergy 261 cout << Verbose(0) << "Old: " << config::RelEpsKineticEnergy << "\t new: "; 262 cin >> config::RelEpsKineticEnergy; 263 break; 264 case 'c': // MaxMinStopStep 265 cout << Verbose(0) << "Old: " << config::MaxMinStopStep << "\t new: "; 266 cin >> config::MaxMinStopStep; 267 break; 268 case 'e': // MaxInitMinStep 269 cout << Verbose(0) << "Old: " << config::MaxInitMinStep << "\t new: "; 270 cin >> config::MaxInitMinStep; 271 break; 272 case 'f': // InitRelEpsTotalEnergy 273 cout << Verbose(0) << "Old: " << config::InitRelEpsTotalEnergy << "\t new: "; 274 cin >> config::InitRelEpsTotalEnergy; 275 break; 276 case 'g': // InitRelEpsKineticEnergy 277 cout << Verbose(0) << "Old: " << config::InitRelEpsKineticEnergy << "\t new: "; 278 cin >> config::InitRelEpsKineticEnergy; 279 break; 280 case 'h': // InitMaxMinStopStep 281 cout << Verbose(0) << "Old: " << config::InitMaxMinStopStep << "\t new: "; 282 cin >> config::InitMaxMinStopStep; 283 break; 284 285 // case 'j': // BoxLength 286 // cout << Verbose(0) << "enter lower triadiagonalo form of basis matrix" << endl << endl; 287 // for (int i=0;i<6;i++) { 288 // cout << Verbose(0) << "Cell size" << i << ": "; 289 // cin >> mol->cell_size[i]; 290 // } 291 // break; 292 293 case 'k': // ECut 294 cout << Verbose(0) << "Old: " << config::ECut << "\t new: "; 295 cin >> config::ECut; 296 break; 297 case 'l': // MaxLevel 298 cout << Verbose(0) << "Old: " << config::MaxLevel << "\t new: "; 299 cin >> config::MaxLevel; 300 break; 301 case 'm': // RiemannTensor 302 cout << Verbose(0) << "Old: " << config::RiemannTensor << "\t new: "; 303 cin >> config::RiemannTensor; 304 break; 305 case 'n': // LevRFactor 306 cout << Verbose(0) << "Old: " << config::LevRFactor << "\t new: "; 307 cin >> config::LevRFactor; 308 break; 309 case 'o': // RiemannLevel 310 cout << Verbose(0) << "Old: " << config::RiemannLevel << "\t new: "; 311 cin >> config::RiemannLevel; 312 break; 313 case 'p': // Lev0Factor 314 cout << Verbose(0) << "Old: " << config::Lev0Factor << "\t new: "; 315 cin >> config::Lev0Factor; 316 break; 317 case 'r': // RTActualUse 318 cout << Verbose(0) << "Old: " << config::RTActualUse << "\t new: "; 319 cin >> config::RTActualUse; 320 break; 321 case 's': // PsiType 322 cout << Verbose(0) << "Old: " << config::PsiType << "\t new: "; 323 cin >> config::PsiType; 324 break; 325 case 't': // MaxPsiDouble 326 cout << Verbose(0) << "Old: " << config::MaxPsiDouble << "\t new: "; 327 cin >> config::MaxPsiDouble; 328 break; 329 case 'u': // PsiMaxNoUp 330 cout << Verbose(0) << "Old: " << config::PsiMaxNoUp << "\t new: "; 331 cin >> config::PsiMaxNoUp; 332 break; 333 case 'v': // PsiMaxNoDown 334 cout << Verbose(0) << "Old: " << config::PsiMaxNoDown << "\t new: "; 335 cin >> config::PsiMaxNoDown; 336 break; 337 case 'w': // AddPsis 338 cout << Verbose(0) << "Old: " << config::AddPsis << "\t new: "; 339 cin >> config::AddPsis; 340 break; 341 342 case 'x': // RCut 343 cout << Verbose(0) << "Old: " << config::RCut << "\t new: "; 344 cin >> config::RCut; 345 break; 346 case 'y': // StructOpt 347 cout << Verbose(0) << "Old: " << config::StructOpt << "\t new: "; 348 cin >> config::StructOpt; 349 break; 350 case 'z': // IsAngstroem 351 cout << Verbose(0) << "Old: " << config::IsAngstroem << "\t new: "; 352 cin >> config::IsAngstroem; 353 break; 354 case 'i': // RelativeCoord 355 cout << Verbose(0) << "Old: " << config::RelativeCoord << "\t new: "; 356 cin >> config::RelativeCoord; 357 break; 358 }; 359 } while (choice != 'q'); 360 360 }; 361 361 … … 368 368 int config::TestSyntax(char *filename, periodentafel *periode, molecule *mol) 369 369 { 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 370 int test; 371 ifstream file(filename); 372 373 // search file for keyword: ProcPEGamma (new syntax) 374 if (ParseForParameter(1,&file,"ProcPEGamma", 0, 1, 1, int_type, &test, 1, optional)) { 375 file.close(); 376 return 1; 377 } 378 // search file for keyword: ProcsGammaPsi (old syntax) 379 if (ParseForParameter(1,&file,"ProcsGammaPsi", 0, 1, 1, int_type, &test, 1, optional)) { 380 file.close(); 381 return 0; 382 } 383 file.close(); 384 return -1; 385 385 } 386 386 … … 390 390 bool config::GetIsAngstroem() const 391 391 { 392 392 return (IsAngstroem == 1); 393 393 }; 394 394 … … 398 398 char * config::GetDefaultPath() const 399 399 { 400 400 return defaultpath; 401 401 }; 402 402 … … 407 407 void config::SetDefaultPath(const char *path) 408 408 { 409 409 strcpy(defaultpath, path); 410 410 }; 411 411 … … 415 415 void config::RetrieveConfigPathAndName(string filename) 416 416 { 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 417 char *ptr = NULL; 418 char *buffer = new char[MAXSTRINGSIZE]; 419 strncpy(buffer, filename.c_str(), MAXSTRINGSIZE); 420 int last = -1; 421 for(last=MAXSTRINGSIZE;last--;) { 422 if (buffer[last] == '/') 423 break; 424 } 425 if (last == -1) { // no path in front, set to local directory. 426 strcpy(configpath, "./"); 427 ptr = buffer; 428 } else { 429 strncpy(configpath, buffer, last+1); 430 ptr = &buffer[last+1]; 431 if (last < 254) 432 configpath[last+1]='\0'; 433 } 434 strcpy(configname, ptr); 435 cout << "Found configpath: " << configpath << ", dir slash was found at " << last << ", config name is " << configname << "." << endl; 436 delete[](buffer); 437 437 }; 438 438 … … 445 445 void config::Load(char *filename, periodentafel *periode, molecule *mol) 446 446 { 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 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 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 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 //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 step719 //cout << ")\t(";720 //for (int d=0;d<NDIM;d++)721 // cout << mol->Trajectories[neues].U.at(repetition).x[d] << " ";// next step722 //cout << ")\t(";723 //for (int d=0;d<NDIM;d++)724 // cout << mol->Trajectories[neues].F.at(repetition).x[d] << " ";// next step725 //cout << ")" << endl;726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 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); 767 767 }; 768 768 … … 774 774 void config::LoadOld(char *filename, periodentafel *periode, molecule *mol) 775 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 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 776 ifstream *file = new ifstream(filename); 777 if (file == NULL) { 778 cerr << "ERROR: config file " << filename << " missing!" << endl; 779 return; 780 } 781 RetrieveConfigPathAndName(filename); 782 // ParseParameters 783 784 /* Oeffne Hauptparameterdatei */ 785 int l, i, di; 786 double a,b; 787 double BoxLength[9]; 788 string zeile; 789 string dummy; 790 element *elementhash[128]; 791 int Z, No, AtomNo, found; 792 int verbose = 0; 793 794 /* Namen einlesen */ 795 796 ParseForParameter(verbose,file, "mainname", 0, 1, 1, string_type, (config::mainname), 1, critical); 797 ParseForParameter(verbose,file, "defaultpath", 0, 1, 1, string_type, (config::defaultpath), 1, critical); 798 ParseForParameter(verbose,file, "pseudopotpath", 0, 1, 1, string_type, (config::pseudopotpath), 1, critical); 799 ParseForParameter(verbose,file, "ProcsGammaPsi", 0, 1, 1, int_type, &(config::ProcPEGamma), 1, critical); 800 ParseForParameter(verbose,file, "ProcsGammaPsi", 0, 2, 1, int_type, &(config::ProcPEPsi), 1, critical); 801 config::Seed = 1; 802 config::DoOutOrbitals = 0; 803 ParseForParameter(verbose,file,"DoOutVis", 0, 1, 1, int_type, &(config::DoOutVis), 1, critical); 804 if (config::DoOutVis < 0) config::DoOutVis = 0; 805 if (config::DoOutVis > 1) config::DoOutVis = 1; 806 config::VectorPlane = -1; 807 config::VectorCut = 0.; 808 ParseForParameter(verbose,file,"DoOutMes", 0, 1, 1, int_type, &(config::DoOutMes), 1, critical); 809 if (config::DoOutMes < 0) config::DoOutMes = 0; 810 if (config::DoOutMes > 1) config::DoOutMes = 1; 811 config::DoOutCurrent = 0; 812 ParseForParameter(verbose,file,"AddGramSch", 0, 1, 1, int_type, &(config::UseAddGramSch), 1, critical); 813 if (config::UseAddGramSch < 0) config::UseAddGramSch = 0; 814 if (config::UseAddGramSch > 2) config::UseAddGramSch = 2; 815 config::CommonWannier = 0; 816 config::SawtoothStart = 0.01; 817 818 ParseForParameter(verbose,file,"MaxOuterStep", 0, 1, 1, double_type, &(config::MaxOuterStep), 1, critical); 819 ParseForParameter(verbose,file,"Deltat", 0, 1, 1, double_type, &(config::Deltat), 1, optional); 820 ParseForParameter(verbose,file,"VisOuterStep", 0, 1, 1, int_type, &(config::OutVisStep), 1, optional); 821 ParseForParameter(verbose,file,"VisSrcOuterStep", 0, 1, 1, int_type, &(config::OutSrcStep), 1, optional); 822 ParseForParameter(verbose,file,"TargetTemp", 0, 1, 1, double_type, &(config::TargetTemp), 1, optional); 823 ParseForParameter(verbose,file,"ScaleTempStep", 0, 1, 1, int_type, &(config::ScaleTempStep), 1, optional); 824 config::EpsWannier = 1e-8; 825 826 // stop conditions 827 //if (config::MaxOuterStep <= 0) config::MaxOuterStep = 1; 828 ParseForParameter(verbose,file,"MaxPsiStep", 0, 1, 1, int_type, &(config::MaxPsiStep), 1, critical); 829 if (config::MaxPsiStep <= 0) config::MaxPsiStep = 3; 830 831 ParseForParameter(verbose,file,"MaxMinStep", 0, 1, 1, int_type, &(config::MaxMinStep), 1, critical); 832 ParseForParameter(verbose,file,"MaxMinStep", 0, 2, 1, double_type, &(config::RelEpsTotalEnergy), 1, critical); 833 ParseForParameter(verbose,file,"MaxMinStep", 0, 3, 1, double_type, &(config::RelEpsKineticEnergy), 1, critical); 834 ParseForParameter(verbose,file,"MaxMinStep", 0, 4, 1, int_type, &(config::MaxMinStopStep), 1, critical); 835 if (config::MaxMinStep <= 0) config::MaxMinStep = config::MaxPsiStep; 836 if (config::MaxMinStopStep < 1) config::MaxMinStopStep = 1; 837 config::MaxMinGapStopStep = 1; 838 839 ParseForParameter(verbose,file,"MaxInitMinStep", 0, 1, 1, int_type, &(config::MaxInitMinStep), 1, critical); 840 ParseForParameter(verbose,file,"MaxInitMinStep", 0, 2, 1, double_type, &(config::InitRelEpsTotalEnergy), 1, critical); 841 ParseForParameter(verbose,file,"MaxInitMinStep", 0, 3, 1, double_type, &(config::InitRelEpsKineticEnergy), 1, critical); 842 ParseForParameter(verbose,file,"MaxInitMinStep", 0, 4, 1, int_type, &(config::InitMaxMinStopStep), 1, critical); 843 if (config::MaxInitMinStep <= 0) config::MaxInitMinStep = config::MaxPsiStep; 844 if (config::InitMaxMinStopStep < 1) config::InitMaxMinStopStep = 1; 845 config::InitMaxMinGapStopStep = 1; 846 847 ParseForParameter(verbose,file, "BoxLength", 0, 3, 3, lower_trigrid, BoxLength, 1, critical); /* Lattice->RealBasis */ 848 mol->cell_size[0] = BoxLength[0]; 849 mol->cell_size[1] = BoxLength[3]; 850 mol->cell_size[2] = BoxLength[4]; 851 mol->cell_size[3] = BoxLength[6]; 852 mol->cell_size[4] = BoxLength[7]; 853 mol->cell_size[5] = BoxLength[8]; 854 if (1) fprintf(stderr,"\n"); 855 config::DoPerturbation = 0; 856 config::DoFullCurrent = 0; 857 858 ParseForParameter(verbose,file,"ECut", 0, 1, 1, double_type, &(config::ECut), 1, critical); 859 ParseForParameter(verbose,file,"MaxLevel", 0, 1, 1, int_type, &(config::MaxLevel), 1, critical); 860 ParseForParameter(verbose,file,"Level0Factor", 0, 1, 1, int_type, &(config::Lev0Factor), 1, critical); 861 if (config::Lev0Factor < 2) { 862 config::Lev0Factor = 2; 863 } 864 ParseForParameter(verbose,file,"RiemannTensor", 0, 1, 1, int_type, &di, 1, critical); 865 if (di >= 0 && di < 2) { 866 config::RiemannTensor = di; 867 } else { 868 fprintf(stderr, "0 <= RiemanTensor < 2: 0 UseNotRT, 1 UseRT"); 869 exit(1); 870 } 871 switch (config::RiemannTensor) { 872 case 0: //UseNoRT 873 if (config::MaxLevel < 2) { 874 config::MaxLevel = 2; 875 } 876 config::LevRFactor = 2; 877 config::RTActualUse = 0; 878 break; 879 case 1: // UseRT 880 if (config::MaxLevel < 3) { 881 config::MaxLevel = 3; 882 } 883 ParseForParameter(verbose,file,"RiemannLevel", 0, 1, 1, int_type, &(config::RiemannLevel), 1, critical); 884 if (config::RiemannLevel < 2) { 885 config::RiemannLevel = 2; 886 } 887 if (config::RiemannLevel > config::MaxLevel-1) { 888 config::RiemannLevel = config::MaxLevel-1; 889 } 890 ParseForParameter(verbose,file,"LevRFactor", 0, 1, 1, int_type, &(config::LevRFactor), 1, critical); 891 if (config::LevRFactor < 2) { 892 config::LevRFactor = 2; 893 } 894 config::Lev0Factor = 2; 895 config::RTActualUse = 2; 896 break; 897 } 898 ParseForParameter(verbose,file,"PsiType", 0, 1, 1, int_type, &di, 1, critical); 899 if (di >= 0 && di < 2) { 900 config::PsiType = di; 901 } else { 902 fprintf(stderr, "0 <= PsiType < 2: 0 UseSpinDouble, 1 UseSpinUpDown"); 903 exit(1); 904 } 905 switch (config::PsiType) { 906 case 0: // SpinDouble 907 ParseForParameter(verbose,file,"MaxPsiDouble", 0, 1, 1, int_type, &(config::MaxPsiDouble), 1, critical); 908 config::AddPsis = 0; 909 break; 910 case 1: // SpinUpDown 911 if (config::ProcPEGamma % 2) config::ProcPEGamma*=2; 912 ParseForParameter(verbose,file,"MaxPsiUp", 0, 1, 1, int_type, &(config::PsiMaxNoUp), 1, critical); 913 ParseForParameter(verbose,file,"MaxPsiDown", 0, 1, 1, int_type, &(config::PsiMaxNoDown), 1, critical); 914 config::AddPsis = 0; 915 break; 916 } 917 918 // IonsInitRead 919 920 ParseForParameter(verbose,file,"RCut", 0, 1, 1, double_type, &(config::RCut), 1, critical); 921 ParseForParameter(verbose,file,"IsAngstroem", 0, 1, 1, int_type, &(config::IsAngstroem), 1, critical); 922 config::RelativeCoord = 0; 923 config::StructOpt = 0; 924 925 // Routine from builder.cpp 926 927 928 for (i=MAX_ELEMENTS;i--;) 929 elementhash[i] = NULL; 930 cout << Verbose(0) << "Parsing Ions ..." << endl; 931 No=0; 932 found = 0; 933 while (getline(*file,zeile,'\n')) { 934 if (zeile.find("Ions_Data") == 0) { 935 cout << Verbose(1) << "found Ions_Data...begin parsing" << endl; 936 found ++; 937 } 938 if (found > 0) { 939 if (zeile.find("Ions_Data") == 0) 940 getline(*file,zeile,'\n'); // read next line and parse this one 941 istringstream input(zeile); 942 input >> AtomNo; // number of atoms 943 input >> Z; // atomic number 944 input >> a; 945 input >> l; 946 input >> l; 947 input >> b; // element mass 948 elementhash[No] = periode->FindElement(Z); 949 cout << Verbose(1) << "AtomNo: " << AtomNo << "\tZ: " << Z << "\ta:" << a << "\tl:" << l << "\b:" << b << "\tElement:" << elementhash[No] << "\t:" << endl; 950 for(i=0;i<AtomNo;i++) { 951 if (!getline(*file,zeile,'\n')) {// parse on and on 952 cout << Verbose(2) << "Error: Too few items in ionic list of element" << elementhash[No] << "." << endl << "Exiting." << endl; 953 // return 1; 954 } else { 955 //cout << Verbose(2) << "Reading line: " << zeile << endl; 956 } 957 istringstream input2(zeile); 958 atom *neues = new atom(); 959 input2 >> neues->x.x[0]; // x 960 input2 >> neues->x.x[1]; // y 961 input2 >> neues->x.x[2]; // z 962 input2 >> l; 963 neues->type = elementhash[No]; // find element type 964 mol->AddAtom(neues); 965 } 966 No++; 967 } 968 } 969 file->close(); 970 delete(file); 971 971 }; 972 972 … … 978 978 bool config::Save(const char *filename, periodentafel *periode, molecule *mol) const 979 979 { 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 //switch (PsiType) {1051 //case 0:1052 1053 //break;1054 //case 1:1055 1056 1057 //break;1058 //}1059 1060 1061 1062 1063 1064 1065 *output << "MaxTypes\t" << mol->ElementCount <<"\t# maximum number of different ion types" << endl;1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 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; 1078 1078 }; 1079 1079 … … 1085 1085 bool config::SaveMPQC(const char *filename, molecule *mol) const 1086 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 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1087 int ElementNo = 0; 1088 int AtomNo; 1089 atom *Walker = NULL; 1090 element *runner = NULL; 1091 Vector *center = NULL; 1092 ofstream *output = NULL; 1093 stringstream *fname = NULL; 1094 1095 // first without hessian 1096 fname = new stringstream; 1097 *fname << filename << ".in"; 1098 output = new ofstream(fname->str().c_str(), ios::out); 1099 *output << "% Created by MoleCuilder" << endl; 1100 *output << "mpqc: (" << endl; 1101 *output << "\tsavestate = no" << endl; 1102 *output << "\tdo_gradient = yes" << endl; 1103 *output << "\tmole<MBPT2>: (" << endl; 1104 *output << "\t\tmaxiter = 200" << endl; 1105 *output << "\t\tbasis = $:basis" << endl; 1106 *output << "\t\tmolecule = $:molecule" << endl; 1107 *output << "\t\treference<CLHF>: (" << endl; 1108 *output << "\t\t\tbasis = $:basis" << endl; 1109 *output << "\t\t\tmolecule = $:molecule" << endl; 1110 *output << "\t\t)" << endl; 1111 *output << "\t)" << endl; 1112 *output << ")" << endl; 1113 *output << "molecule<Molecule>: (" << endl; 1114 *output << "\tunit = " << (IsAngstroem ? "angstrom" : "bohr" ) << endl; 1115 *output << "\t{ atoms geometry } = {" << endl; 1116 center = mol->DetermineCenterOfAll(output); 1117 // output of atoms 1118 runner = mol->elemente->start; 1119 while (runner->next != mol->elemente->end) { // go through every element 1120 runner = runner->next; 1121 if (mol->ElementsInMolecule[runner->Z]) { // if this element got atoms 1122 ElementNo++; 1123 AtomNo = 0; 1124 Walker = mol->start; 1125 while (Walker->next != mol->end) { // go through every atom of this element 1126 Walker = Walker->next; 1127 if (Walker->type == runner) { // if this atom fits to element 1128 AtomNo++; 1129 *output << "\t\t" << Walker->type->symbol << " [ " << Walker->x.x[0]-center->x[0] << "\t" << Walker->x.x[1]-center->x[1] << "\t" << Walker->x.x[2]-center->x[2] << " ]" << endl; 1130 } 1131 } 1132 } 1133 } 1134 delete(center); 1135 *output << "\t}" << endl; 1136 *output << ")" << endl; 1137 *output << "basis<GaussianBasisSet>: (" << endl; 1138 *output << "\tname = \""<< basis << "\"" << endl; 1139 *output << "\tmolecule = $:molecule" << endl; 1140 *output << ")" << endl; 1141 output->close(); 1142 delete(output); 1143 delete(fname); 1144 1145 // second with hessian 1146 fname = new stringstream; 1147 *fname << filename << ".hess.in"; 1148 output = new ofstream(fname->str().c_str(), ios::out); 1149 *output << "% Created by MoleCuilder" << endl; 1150 *output << "mpqc: (" << endl; 1151 *output << "\tsavestate = no" << endl; 1152 *output << "\tdo_gradient = yes" << endl; 1153 *output << "\tmole<CLHF>: (" << endl; 1154 *output << "\t\tmaxiter = 200" << endl; 1155 *output << "\t\tbasis = $:basis" << endl; 1156 *output << "\t\tmolecule = $:molecule" << endl; 1157 *output << "\t)" << endl; 1158 *output << "\tfreq<MolecularFrequencies>: (" << endl; 1159 *output << "\t\tmolecule=$:molecule" << endl; 1160 *output << "\t)" << endl; 1161 *output << ")" << endl; 1162 *output << "molecule<Molecule>: (" << endl; 1163 *output << "\tunit = " << (IsAngstroem ? "angstrom" : "bohr" ) << endl; 1164 *output << "\t{ atoms geometry } = {" << endl; 1165 center = mol->DetermineCenterOfAll(output); 1166 // output of atoms 1167 runner = mol->elemente->start; 1168 while (runner->next != mol->elemente->end) { // go through every element 1169 runner = runner->next; 1170 if (mol->ElementsInMolecule[runner->Z]) { // if this element got atoms 1171 ElementNo++; 1172 AtomNo = 0; 1173 Walker = mol->start; 1174 while (Walker->next != mol->end) { // go through every atom of this element 1175 Walker = Walker->next; 1176 if (Walker->type == runner) { // if this atom fits to element 1177 AtomNo++; 1178 *output << "\t\t" << Walker->type->symbol << " [ " << Walker->x.x[0]-center->x[0] << "\t" << Walker->x.x[1]-center->x[1] << "\t" << Walker->x.x[2]-center->x[2] << " ]" << endl; 1179 } 1180 } 1181 } 1182 } 1183 delete(center); 1184 *output << "\t}" << endl; 1185 *output << ")" << endl; 1186 *output << "basis<GaussianBasisSet>: (" << endl; 1187 *output << "\tname = \"3-21G\"" << endl; 1188 *output << "\tmolecule = $:molecule" << endl; 1189 *output << ")" << endl; 1190 output->close(); 1191 delete(output); 1192 delete(fname); 1193 1194 return true; 1195 1195 }; 1196 1196 … … 1204 1204 * \param name Name of value in file (at least 3 chars!) 1205 1205 * \param sequential 1 - do not reset file pointer to begin of file, 0 - set to beginning 1206 * 1207 * 1208 * 1206 * (if file is sequentially parsed this can be way faster! However, beware of multiple values per line, as whole line is read - 1207 * best approach: 0 0 0 1 (not resetted only on last value of line) - and of yth, which is now 1208 * counted from this unresetted position!) 1209 1209 * \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 1210 * \param yth In grid case specifying column number, otherwise the yth \a name matching line … … 1217 1217 */ 1218 1218 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 1219 int i,j; // loop variables 1220 int length = 0, maxlength = -1; 1221 long file_position = file->tellg(); // mark current position 1222 char *dummy1, *dummy, *free_dummy; // pointers in the line that is read in per step 1223 dummy1 = free_dummy = (char *) Malloc(256 * sizeof(char), "config::ParseForParameter: *free_dummy"); 1224 1225 //fprintf(stderr,"Parsing for %s\n",name); 1226 if (repetition == 0) 1227 //Error(SomeError, "ParseForParameter(): argument repetition must not be 0!"); 1228 return 0; 1229 1230 int line = 0; // marks line where parameter was found 1231 int found = (type >= grid) ? 0 : (-yth + 1); // marks if yth parameter name was found 1232 while((found != repetition)) { 1233 dummy1 = dummy = free_dummy; 1234 do { 1235 file->getline(dummy1, 256); // Read the whole line 1236 if (file->eof()) { 1237 if ((critical) && (found == 0)) { 1238 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1239 //Error(InitReading, name); 1240 fprintf(stderr,"Error:InitReading, critical %s not found\n", name); 1241 exit(255); 1242 } else { 1243 //if (!sequential) 1244 file->clear(); 1245 file->seekg(file_position, ios::beg); // rewind to start position 1246 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1247 return 0; 1248 } 1249 } 1250 line++; 1251 } while (dummy != NULL && dummy1 != NULL && ((dummy1[0] == '#') || (dummy1[0] == '\0'))); // skip commentary and empty lines 1252 1253 // C++ getline removes newline at end, thus re-add 1254 if ((dummy1 != NULL) && (strchr(dummy1,'\n') == NULL)) { 1255 i = strlen(dummy1); 1256 dummy1[i] = '\n'; 1257 dummy1[i+1] = '\0'; 1258 } 1259 //fprintf(stderr,"line %i ends at %i, newline at %i\n", line, strlen(dummy1), strchr(dummy1,'\n')-free_dummy); 1260 1261 if (dummy1 == NULL) { 1262 if (verbose) fprintf(stderr,"Error reading line %i\n",line); 1263 } else { 1264 //fprintf(stderr,"Now parsing the line %i: %s\n", line, dummy1); 1265 } 1266 // Seek for possible end of keyword on line if given ... 1267 if (name != NULL) { 1268 dummy = strchr(dummy1,'\t'); // set dummy on first tab or space which ever's nearer 1269 if (dummy == NULL) { 1270 dummy = strchr(dummy1, ' '); // if not found seek for space 1271 while ((dummy != NULL) && ((*dummy == '\t') || (*dummy == ' '))) // skip some more tabs and spaces if necessary 1272 dummy++; 1273 } 1274 if (dummy == NULL) { 1275 dummy = strchr(dummy1, '\n'); // set on line end then (whole line = keyword) 1276 //fprintf(stderr,"Error: Cannot find tabs or spaces on line %i in search for %s\n", line, name); 1277 //Free((void **)&free_dummy); 1278 //Error(FileOpenParams, NULL); 1279 } else { 1280 //fprintf(stderr,"found tab at %i\n",(char *)dummy-(char *)dummy1); 1281 } 1282 } else dummy = dummy1; 1283 // ... and check if it is the keyword! 1284 //fprintf(stderr,"name %p, dummy %i/%c, dummy1 %i/%c, strlen(name) %i\n", &name, dummy, *dummy, dummy1, *dummy1, strlen(name)); 1285 if ((name == NULL) || (((dummy-dummy1 >= 3) && (strncmp(dummy1, name, strlen(name)) == 0)) && ((unsigned int)(dummy-dummy1) == strlen(name)))) { 1286 found++; // found the parameter! 1287 //fprintf(stderr,"found %s at line %i between %i and %i\n", name, line, dummy1, dummy); 1288 1289 if (found == repetition) { 1290 for (i=0;i<xth;i++) { // i = rows 1291 if (type >= grid) { 1292 // grid structure means that grid starts on the next line, not right after keyword 1293 dummy1 = dummy = free_dummy; 1294 do { 1295 file->getline(dummy1, 256); // Read the whole line, skip commentary and empty ones 1296 if (file->eof()) { 1297 if ((critical) && (found == 0)) { 1298 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1299 //Error(InitReading, name); 1300 fprintf(stderr,"Error:InitReading, critical %s not found\n", name); 1301 exit(255); 1302 } else { 1303 //if (!sequential) 1304 file->clear(); 1305 file->seekg(file_position, ios::beg); // rewind to start position 1306 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1307 return 0; 1308 } 1309 } 1310 line++; 1311 } while ((dummy1[0] == '#') || (dummy1[0] == '\n')); 1312 if (dummy1 == NULL){ 1313 if (verbose) fprintf(stderr,"Error reading line %i\n", line); 1314 } else { 1315 //fprintf(stderr,"Reading next line %i: %s\n", line, dummy1); 1316 } 1317 } else { // simple int, strings or doubles start in the same line 1318 while ((*dummy == '\t') || (*dummy == ' ')) // skip interjacent tabs and spaces 1319 dummy++; 1320 } 1321 // C++ getline removes newline at end, thus re-add 1322 if ((dummy1 != NULL) && (strchr(dummy1,'\n') == NULL)) { 1323 j = strlen(dummy1); 1324 dummy1[j] = '\n'; 1325 dummy1[j+1] = '\0'; 1326 } 1327 1328 int start = (type >= grid) ? 0 : yth-1 ; 1329 for (j=start;j<yth;j++) { // j = columns 1330 // check for lower triangular area and upper triangular area 1331 if ( ((i > j) && (type == upper_trigrid)) || ((j > i) && (type == lower_trigrid))) { 1332 *((double *)value) = 0.0; 1333 fprintf(stderr,"%f\t",*((double *)value)); 1334 value = (void *)((long)value + sizeof(double)); 1335 //value += sizeof(double); 1336 } else { 1337 // otherwise we must skip all interjacent tabs and spaces and find next value 1338 dummy1 = dummy; 1339 dummy = strchr(dummy1, '\t'); // seek for tab or space 1340 if (dummy == NULL) 1341 dummy = strchr(dummy1, ' '); // if not found seek for space 1342 if (dummy == NULL) { // if still zero returned ... 1343 dummy = strchr(dummy1, '\n'); // ... at line end then 1344 if ((j < yth-1) && (type < 4)) { // check if xth value or not yet 1345 if (critical) { 1346 if (verbose) fprintf(stderr,"Error: EoL at %i and still missing %i value(s) for parameter %s\n", line, yth-j, name); 1347 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1348 //return 0; 1349 exit(255); 1350 //Error(FileOpenParams, NULL); 1351 } else { 1352 //if (!sequential) 1353 file->clear(); 1354 file->seekg(file_position, ios::beg); // rewind to start position 1355 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1356 return 0; 1357 } 1358 } 1359 } else { 1360 //fprintf(stderr,"found tab at %i\n",(char *)dummy-(char *)free_dummy); 1361 } 1362 if (*dummy1 == '#') { 1363 // found comment, skipping rest of line 1364 //if (verbose) fprintf(stderr,"Error: '#' at %i and still missing %i value(s) for parameter %s\n", line, yth-j, name); 1365 if (!sequential) { // here we need it! 1366 file->seekg(file_position, ios::beg); // rewind to start position 1367 } 1368 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1369 return 0; 1370 } 1371 //fprintf(stderr,"value from %i to %i\n",(char *)dummy1-(char *)free_dummy,(char *)dummy-(char *)free_dummy); 1372 switch(type) { 1373 case (row_int): 1374 *((int *)value) = atoi(dummy1); 1375 if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name); 1376 if (verbose) fprintf(stderr,"%i\t",*((int *)value)); 1377 value = (void *)((long)value + sizeof(int)); 1378 //value += sizeof(int); 1379 break; 1380 case(row_double): 1381 case(grid): 1382 case(lower_trigrid): 1383 case(upper_trigrid): 1384 *((double *)value) = atof(dummy1); 1385 if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name); 1386 if (verbose) fprintf(stderr,"%lg\t",*((double *)value)); 1387 value = (void *)((long)value + sizeof(double)); 1388 //value += sizeof(double); 1389 break; 1390 case(double_type): 1391 *((double *)value) = atof(dummy1); 1392 if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %lg\n", name, *((double *) value)); 1393 //value += sizeof(double); 1394 break; 1395 case(int_type): 1396 *((int *)value) = atoi(dummy1); 1397 if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %i\n", name, *((int *) value)); 1398 //value += sizeof(int); 1399 break; 1400 default: 1401 case(string_type): 1402 if (value != NULL) { 1403 //if (maxlength == -1) maxlength = strlen((char *)value); // get maximum size of string array 1404 maxlength = MAXSTRINGSIZE; 1405 length = maxlength > (dummy-dummy1) ? (dummy-dummy1) : maxlength; // cap at maximum 1406 strncpy((char *)value, dummy1, length); // copy as much 1407 ((char *)value)[length] = '\0'; // and set end marker 1408 if ((verbose) && (i == xth-1)) fprintf(stderr,"%s is '%s' (%i chars)\n",name,((char *) value), length); 1409 //value += sizeof(char); 1410 } else { 1411 } 1412 break; 1413 } 1414 } 1415 while (*dummy == '\t') 1416 dummy++; 1417 } 1418 } 1419 } 1420 } 1421 } 1422 if ((type >= row_int) && (verbose)) fprintf(stderr,"\n"); 1423 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1424 if (!sequential) { 1425 file->clear(); 1426 file->seekg(file_position, ios::beg); // rewind to start position 1427 } 1428 //fprintf(stderr, "End of Parsing\n\n"); 1429 1430 return (found); // true if found, false if not 1431 1431 } -
src/datacreator.cpp
r178f92 r437922 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 66 67 68 69 70 71 72 73 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 << endl; 66 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 67 for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) { 68 for(int j=Fragments.RowCounter[ KeySet.OrderSet[BondOrder][i] ];j--;) 69 for(int k=Fragments.ColumnCounter;k--;) 70 Fragments.Matrix[Fragments.MatrixCounter][j][k] += Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 71 } 72 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder]; 73 for (int l=0;l<Fragments.ColumnCounter;l++) 74 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l]; 75 output << endl; 76 } 77 output.close(); 78 return true; 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 99 100 101 102 103 104 105 106 107 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 << endl; 99 Fragments.SetLastMatrix(Energy.Matrix[Energy.MatrixCounter],0); 100 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 101 for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) { 102 for(int j=Fragments.RowCounter[ KeySet.OrderSet[BondOrder][i] ];j--;) 103 for(int k=Fragments.ColumnCounter;k--;) 104 Fragments.Matrix[Fragments.MatrixCounter][j][k] -= Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 105 } 106 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder]; 107 for (int l=0;l<Fragments.ColumnCounter;l++) 108 if (fabs(Energy.Matrix[Energy.MatrixCounter][ Energy.RowCounter[Energy.MatrixCounter]-1 ][l]) < MYEPSILON) 109 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l]; 110 else 111 output << scientific << "\t" << (Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l] / Energy.Matrix[Energy.MatrixCounter][ Energy.RowCounter[Energy.MatrixCounter]-1 ][l]); 112 output << endl; 113 } 114 output.close(); 115 return true; 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 136 137 138 139 140 141 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 << endl; 136 Fragments.SetLastMatrix(0.,0); 137 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 138 Fragments.SumSubForces(Fragments, KeySet, BondOrder, 1.); 139 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder]; 140 CreateForce(Fragments, Fragments.MatrixCounter); 141 for (int l=0;l<Fragments.ColumnCounter;l++) 142 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter] ][l]; 143 output << endl; 144 } 145 output.close(); 146 return true; 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 168 169 170 171 172 173 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 << endl; 168 Fragments.SetLastMatrix(Force.Matrix[Force.MatrixCounter],0); 169 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 170 Fragments.SumSubForces(Fragments, KeySet, BondOrder, -1.); 171 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder]; 172 CreateForce(Fragments, Fragments.MatrixCounter); 173 for (int l=0;l<Fragments.ColumnCounter;l++) 174 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter] ][l]; 175 output << endl; 176 } 177 output.close(); 178 return true; 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 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 192 stringstream filename; 193 ofstream output; 194 double norm = 0.; 195 196 filename << prefix << ".dat"; 197 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 198 cout << msg << endl; 199 output << "# " << msg << ", created on " << datum; 200 output << "# AtomNo\t" << Fragments.Header << endl; 201 Fragments.SetLastMatrix(Force.Matrix[Force.MatrixCounter], 0); 202 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 203 //cout << "Current order is " << BondOrder << "." << endl; 204 Fragments.SumSubForces(Fragments, KeySet, BondOrder, -1.); 205 // errors per atom 206 output << endl << "#Order\t" << BondOrder+1 << endl; 207 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) { 208 output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t"; 209 for (int l=0;l<Fragments.ColumnCounter;l++) { 210 if (((l+1) % 3) == 0) { 211 norm = 0.; 212 for (int m=0;m<NDIM;m++) 213 norm += Force.Matrix[Force.MatrixCounter][ j ][l+m]*Force.Matrix[Force.MatrixCounter][ j ][l+m]; 214 norm = sqrt(norm); 215 } 216 // if (norm < MYEPSILON) 217 output << scientific << Fragments.Matrix[Fragments.MatrixCounter][ j ][l] << "\t"; 218 // else 219 // output << scientific << (Fragments.Matrix[Fragments.MatrixCounter][ j ][l] / norm) << "\t"; 220 } 221 output << endl; 222 } 223 output << endl; 224 } 225 output.close(); 226 return true; 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 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 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; 262 262 }; 263 263 … … 266 266 bool CreateDataFragment(class MatrixContainer &Fragment, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateFragment)(class MatrixContainer &, int)) 267 267 { 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 268 stringstream filename; 269 ofstream output; 270 271 filename << prefix << ".dat"; 272 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 273 cout << msg << endl; 274 output << "# " << msg << ", created on " << datum << endl; 275 output << "#Order\tFrag.No.\t" << Fragment.Header << endl; 276 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 277 for(int i=0;i<KeySet.FragmentsPerOrder[BondOrder];i++) { 278 output << BondOrder+1 << "\t" << KeySet.OrderSet[BondOrder][i]+1; 279 CreateFragment(Fragment, KeySet.OrderSet[BondOrder][i]); 280 for (int l=0;l<Fragment.ColumnCounter;l++) 281 output << scientific << "\t" << Fragment.Matrix[ KeySet.OrderSet[BondOrder][i] ][ Fragment.RowCounter[ KeySet.OrderSet[BondOrder][i] ] ][l]; 282 output << endl; 283 } 284 } 285 output.close(); 286 return true; 287 287 }; 288 288 … … 294 294 void CreateMaxFragmentOrder(class MatrixContainer &Fragments, class KeySetsContainer &KeySet, int BondOrder) 295 295 { 296 297 298 299 300 301 302 303 296 for(int j=Fragments.RowCounter[ Fragments.MatrixCounter ];j--;) { 297 for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) { 298 if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) < fabs(Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][1])) { 299 for (int k=Fragments.ColumnCounter;k--;) 300 Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 301 } 302 } 303 } 304 304 }; 305 305 … … 311 311 void CreateMinFragmentOrder(class MatrixContainer &Fragments, class KeySetsContainer &KeySet, int BondOrder) 312 312 { 313 314 315 do {// first get a minimum value unequal to 0316 317 318 319 320 321 322 323 324 325 326 313 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) { 314 int i=0; 315 do { // first get a minimum value unequal to 0 316 for (int k=Fragments.ColumnCounter;k--;) 317 Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 318 i++; 319 } while ((fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) < MYEPSILON) && (i<KeySet.FragmentsPerOrder[BondOrder])); 320 for(;i<KeySet.FragmentsPerOrder[BondOrder];i++) { // then find lowest 321 if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) > fabs(Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][1])) { 322 for (int k=Fragments.ColumnCounter;k--;) 323 Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 324 } 325 } 326 } 327 327 }; 328 328 … … 331 331 bool CreateDataFragmentOrder(class MatrixContainer &Fragment, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateFragmentOrder)(class MatrixContainer &, class KeySetsContainer &, int)) 332 332 { 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 333 stringstream filename; 334 ofstream output; 335 336 filename << prefix << ".dat"; 337 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 338 cout << msg << endl; 339 output << "# " << msg << ", created on " << datum; 340 output << "#Order\tFrag.No.\t" << Fragment.Header << endl; 341 // max 342 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 343 Fragment.SetLastMatrix(0.,0); 344 CreateFragmentOrder(Fragment, KeySet, BondOrder); 345 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder]; 346 for (int l=0;l<Fragment.ColumnCounter;l++) 347 output << scientific << "\t" << Fragment.Matrix[ Fragment.MatrixCounter ][ Fragment.RowCounter[ Fragment.MatrixCounter ]-1 ][l]; 348 output << endl; 349 } 350 output.close(); 351 return true; 352 352 }; 353 353 … … 358 358 void CreateEnergy(class MatrixContainer &Energy, int MatrixNumber) 359 359 { 360 361 Energy.Matrix[MatrixNumber][ Energy.RowCounter[MatrixNumber] ] [k] =Energy.Matrix[MatrixNumber][ Energy.RowCounter[MatrixNumber]-1 ] [k];360 for(int k=0;k<Energy.ColumnCounter;k++) 361 Energy.Matrix[MatrixNumber][ Energy.RowCounter[MatrixNumber] ] [k] = Energy.Matrix[MatrixNumber][ Energy.RowCounter[MatrixNumber]-1 ] [k]; 362 362 }; 363 363 … … 369 369 void CreateMinimumForce(class MatrixContainer &Force, int MatrixNumber) 370 370 { 371 372 373 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 371 for (int l=Force.ColumnCounter;l--;) 372 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.; 373 for (int l=5;l<Force.ColumnCounter;l+=3) { 374 double stored = 0; 375 int k=0; 376 do { 377 for (int m=NDIM;m--;) { 378 stored += Force.Matrix[MatrixNumber][ k ][l+m] 379 * Force.Matrix[MatrixNumber][ k ][l+m]; 380 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m] = Force.Matrix[MatrixNumber][ k ][l+m]; 381 } 382 k++; 383 } while ((fabs(stored) < MYEPSILON) && (k<Force.RowCounter[MatrixNumber])); 384 for (;k<Force.RowCounter[MatrixNumber];k++) { 385 double tmp = 0; 386 for (int m=NDIM;m--;) 387 tmp += Force.Matrix[MatrixNumber][ k ][l+m] 388 * Force.Matrix[MatrixNumber][ k ][l+m]; 389 if ((fabs(tmp) > MYEPSILON) && (tmp < stored)) { // current force is greater than stored 390 for (int m=NDIM;m--;) 391 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m] = Force.Matrix[MatrixNumber][ k ][l+m]; 392 stored = tmp; 393 } 394 } 395 } 396 396 }; 397 397 … … 399 399 * Results are stored in the matrix ForceMatrix::MatrixCounter of \a Force. 400 400 * \param Force ForceMatrix class containing matrix values 401 401 * \param MatrixNumber the index for the ForceMatrix::matrix array 402 402 */ 403 403 void CreateMeanForce(class MatrixContainer &Force, int MatrixNumber) 404 404 { 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 405 int divisor = 0; 406 for (int l=Force.ColumnCounter;l--;) 407 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.; 408 for (int l=5;l<Force.ColumnCounter;l+=3) { 409 double tmp = 0; 410 for (int k=Force.RowCounter[MatrixNumber];k--;) { 411 double norm = 0.; 412 for (int m=NDIM;m--;) 413 norm += Force.Matrix[MatrixNumber][ k ][l+m] 414 * Force.Matrix[MatrixNumber][ k ][l+m]; 415 tmp += sqrt(norm); 416 if (fabs(norm) > MYEPSILON) divisor++; 417 } 418 tmp /= (double)divisor; 419 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = tmp; 420 } 421 421 }; 422 422 … … 428 428 void CreateMaximumForce(class MatrixContainer &Force, int MatrixNumber) 429 429 { 430 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 430 for (int l=5;l<Force.ColumnCounter;l+=3) { 431 double stored = 0; 432 for (int k=Force.RowCounter[MatrixNumber];k--;) { 433 double tmp = 0; 434 for (int m=NDIM;m--;) 435 tmp += Force.Matrix[MatrixNumber][ k ][l+m] 436 * Force.Matrix[MatrixNumber][ k ][l+m]; 437 if (tmp > stored) { // current force is greater than stored 438 for (int m=NDIM;m--;) 439 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m] = Force.Matrix[MatrixNumber][ k ][l+m]; 440 stored = tmp; 441 } 442 } 443 } 444 444 }; 445 445 … … 450 450 void CreateSameForce(class MatrixContainer &Force, int MatrixNumber) 451 451 { 452 452 // does nothing 453 453 }; 454 454 … … 460 460 void CreateVectorSumForce(class MatrixContainer &Force, int MatrixNumber) 461 461 { 462 463 464 465 466 467 462 for (int l=Force.ColumnCounter;l--;) 463 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.; 464 for (int l=0;l<Force.ColumnCounter;l++) { 465 for (int k=Force.RowCounter[MatrixNumber];k--;) 466 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] += Force.Matrix[MatrixNumber][k][l]; 467 } 468 468 }; 469 469 … … 480 480 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 481 { 482 483 484 485 486 487 488 489 490 491 492 493 494 495 482 //output << "#!/home/heber/build/pyxplot/pyxplot" << endl << endl; 483 output << "reset" << endl; 484 output << "set keycolumns "<< keycolumns << endl; 485 output << "set key " << key << endl; 486 output << "set mxtics "<< mxtics << endl; 487 output << "set xtics "<< xtics << endl; 488 if (logscale != NULL) 489 output << "set logscale " << logscale << endl; 490 if (extraline != NULL) 491 output << extraline << endl; 492 output << "set xlabel '" << xlabel << "'" << endl; 493 output << "set ylabel '" << ylabel << "'" << endl; 494 output << "set terminal eps color" << endl; 495 output << "set output '"<< prefix << ".eps'" << endl; 496 496 }; 497 497 … … 517 517 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 518 { 519 520 521 522 523 524 525 526 527 528 519 stringstream filename; 520 ofstream output; 521 522 filename << prefix << ".pyx"; 523 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 524 CreatePlotHeader(output, prefix, keycolumns, key, logscale, extraline, mxtics, xtics, xlabel, ylabel); 525 output << "plot " << xrange << " " << yrange << " \\" << endl; 526 CreatePlotLines(output, Matrix, prefix, xargument, uses); 527 output.close(); 528 return true; 529 529 }; 530 530 … … 538 538 void AbsEnergyPlotLine(ofstream &output, class MatrixContainer &Energy, const char *prefix, const char *xargument, const char *uses) 539 539 { 540 541 542 543 544 545 546 547 548 549 550 551 552 540 stringstream line(Energy.Header); 541 string token; 542 543 getline(line, token, '\t'); 544 for (int i=2; i<= Energy.ColumnCounter;i++) { 545 getline(line, token, '\t'); 546 while (token[0] == ' ') // remove leading white spaces 547 token.erase(0,1); 548 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(abs($" << i+2 << ")) " << uses; 549 if (i != (Energy.ColumnCounter)) 550 output << ", \\"; 551 output << endl; 552 } 553 553 }; 554 554 … … 562 562 void EnergyPlotLine(ofstream &output, class MatrixContainer &Energy, const char *prefix, const char *xargument, const char *uses) 563 563 { 564 565 566 567 568 569 570 571 572 573 574 575 576 564 stringstream line(Energy.Header); 565 string token; 566 567 getline(line, token, '\t'); 568 for (int i=1; i<= Energy.ColumnCounter;i++) { 569 getline(line, token, '\t'); 570 while (token[0] == ' ') // remove leading white spaces 571 token.erase(0,1); 572 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":" << i+2 << " " << uses; 573 if (i != (Energy.ColumnCounter)) 574 output << ", \\"; 575 output << endl; 576 } 577 577 }; 578 578 … … 586 586 void ForceMagnitudePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses) 587 587 { 588 589 590 591 592 593 594 595 596 597 598 599 600 token.erase(token.length(), 1);// kill residual index char (the '0')601 602 603 604 605 606 607 588 stringstream line(Force.Header); 589 string token; 590 591 getline(line, token, '\t'); 592 getline(line, token, '\t'); 593 getline(line, token, '\t'); 594 getline(line, token, '\t'); 595 getline(line, token, '\t'); 596 for (int i=7; i< Force.ColumnCounter;i+=NDIM) { 597 getline(line, token, '\t'); 598 while (token[0] == ' ') // remove leading white spaces 599 token.erase(0,1); 600 token.erase(token.length(), 1); // kill residual index char (the '0') 601 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(sqrt($" << i+1 << "*$" << i+1 << "+$" << i+2 << "*$" << i+2 << "+$" << i+3 << "*$" << i+3 << ")) " << uses; 602 if (i != (Force.ColumnCounter-1)) 603 output << ", \\"; 604 output << endl; 605 getline(line, token, '\t'); 606 getline(line, token, '\t'); 607 } 608 608 }; 609 609 … … 617 617 void AbsFirstForceValuePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses) 618 618 { 619 620 621 622 623 624 625 626 627 628 629 630 631 token.erase(token.length(), 1);// kill residual index char (the '0')632 633 634 635 636 637 638 619 stringstream line(Force.Header); 620 string token; 621 622 getline(line, token, '\t'); 623 getline(line, token, '\t'); 624 getline(line, token, '\t'); 625 getline(line, token, '\t'); 626 getline(line, token, '\t'); 627 for (int i=7; i< Force.ColumnCounter;i+=NDIM) { 628 getline(line, token, '\t'); 629 while (token[0] == ' ') // remove leading white spaces 630 token.erase(0,1); 631 token.erase(token.length(), 1); // kill residual index char (the '0') 632 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(abs($" << i+1 << ")) " << uses; 633 if (i != (Force.ColumnCounter-1)) 634 output << ", \\"; 635 output << endl; 636 getline(line, token, '\t'); 637 getline(line, token, '\t'); 638 } 639 639 }; 640 640 … … 648 648 void BoxesForcePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses) 649 649 { 650 651 652 653 654 655 656 657 658 659 660 661 662 663 token.erase(token.length(), 1);// kill residual index char (the '0')664 665 666 667 668 669 670 650 stringstream line(Force.Header); 651 char *fillcolor[5] = {"black", "red", "blue", "green", "cyan"}; 652 string token; 653 654 getline(line, token, '\t'); 655 getline(line, token, '\t'); 656 getline(line, token, '\t'); 657 getline(line, token, '\t'); 658 getline(line, token, '\t'); 659 for (int i=7; i< Force.ColumnCounter;i+=NDIM) { 660 getline(line, token, '\t'); 661 while (token[0] == ' ') // remove leading white spaces 662 token.erase(0,1); 663 token.erase(token.length(), 1); // kill residual index char (the '0') 664 output << "'" << prefix << ".dat' title '" << token << "' using ($" << xargument << "+" << fixed << setprecision(1) << (double)((i-7)/3)*0.2 << "):(sqrt($" << i+1 << "*$" << i+1 << "+$" << i+2 << "*$" << i+2 << "+$" << i+3 << "*$" << i+3 << ")) " << uses << " " << fillcolor[(i-7)/3]; 665 if (i != (Force.ColumnCounter-1)) 666 output << ", \\"; 667 output << endl; 668 getline(line, token, '\t'); 669 getline(line, token, '\t'); 670 } 671 671 }; 672 672 … … 680 680 void BoxesFirstForceValuePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses) 681 681 { 682 683 684 685 686 687 688 689 690 691 692 693 694 695 token.erase(token.length(), 1);// kill residual index char (the '0')696 697 698 699 700 701 702 703 }; 682 stringstream line(Force.Header); 683 char *fillcolor[5] = {"black", "red", "blue", "green", "cyan"}; 684 string token; 685 686 getline(line, token, '\t'); 687 getline(line, token, '\t'); 688 getline(line, token, '\t'); 689 getline(line, token, '\t'); 690 getline(line, token, '\t'); 691 for (int i=7; i< Force.ColumnCounter;i+=NDIM) { 692 getline(line, token, '\t'); 693 while (token[0] == ' ') // remove leading white spaces 694 token.erase(0,1); 695 token.erase(token.length(), 1); // kill residual index char (the '0') 696 output << "'" << prefix << ".dat' title '" << token << "' using ($" << xargument << "+" << fixed << setprecision(1) << (double)((i-7)/3)*0.2 << "):" << i+1 << " " << uses << " " << fillcolor[(i-7)/3]; 697 if (i != (Force.ColumnCounter-1)) 698 output << ", \\"; 699 output << endl; 700 getline(line, token, '\t'); 701 getline(line, token, '\t'); 702 } 703 }; -
src/defs.hpp
r178f92 r437922 10 10 using namespace std; 11 11 12 #define MYEPSILON 1e-13 13 #define NDIM 3//!< number of spatial dimensions14 #define MAX_ELEMENTS 128 15 #define AtomicLengthToAngstroem 16 #define BONDTHRESHOLD 0.5 17 #define AtomicEnergyToKelvin 315774.67 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 18 #define VERSIONSTRING "v1.0" 19 19 … … 24 24 enum EdgeType { Undetermined, TreeEdge, BackEdge }; //!< edge type in a graph after Depth-First-Search analysis. 25 25 26 enum Shading { white, lightgray, darkgray, black }; 26 enum Shading { white, lightgray, darkgray, black }; //!< color in Breadth-First-Search analysis 27 27 28 //enum CutCyclicBond { KeepBond, 28 //enum CutCyclicBond { KeepBond, SaturateBond }; //!< Saturation scheme either atom- or bondwise 29 29 30 30 // 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 31 enum necessity { optional, //!< parameter is optional, if not given sensible value is chosen 32 critical //!< parameter must be given or programme won't initiate 33 }; 34 34 35 35 // Specifying the status of the on command line given config file … … 43 43 44 44 // 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" 45 #define DEFAULTCONFIG "main_pcp_linux" //!< default filename of config file 46 #define CONVEXENVELOPE "ConvexEnvelope.dat" //!< default filename of convex envelope tecplot data file 47 #define KEYSETFILE "KeySets.dat" //!< default filename of BOSSANOVA key sets file 48 #define ADJACENCYFILE "Adjacency.dat" //!< default filename of BOSSANOVA adjacancy file 49 #define TEFACTORSFILE "TE-Factors.dat" //!< default filename of BOSSANOVA total energy factors file 50 #define FORCESFILE "Forces-Factors.dat" //!< default filename of BOSSANOVA force factors file 51 #define HCORRECTIONSUFFIX "Hcorrection.dat" //!< default filename of BOSSANOVA H correction file (unwanted saturation interaction) 52 #define FITCONSTANTSUFFIX "FitConstant.dat" //!< suffix of default filename of BOSSANOVA fit constants file (unwanted saturation interaction) 53 #define SHIELDINGSUFFIX "sigma_all.csv" //!< default filename of BOSSANOVA shieldings file 54 #define SHIELDINGPASSUFFIX "sigma_all_PAS.csv" //!< default filename of BOSSANOVA shieldings PAS file 55 #define ORDERATSITEFILE "OrderAtSite.dat" //!< default filename of BOSSANOVA Bond Order at each atom file 56 #define ENERGYPERFRAGMENT "EnergyPerFragment" //!< default filename of BOSSANOVA Energy contribution Per Fragment file 57 #define FRAGMENTPREFIX "BondFragment" //!< default filename prefix of BOSSANOVA fragment config and directories 58 #define STANDARDCONFIG "unknown.conf" //!< default filename of standard config file 59 #define STANDARDELEMENTSDB "elements.db" //!< default filename of elements data base with masses, Z, VanDerWaals radii, ... 60 #define STANDARDVALENCEDB "valence.db" //!< default filename of valence number per element database 61 #define STANDARDORBITALDB "orbitals.db" //!< default filename of orbitals per element database 62 #define STANDARDHBONDDISTANCEDB "Hbonddistance.db" //!< default filename of typial bond distance to hydrogen database 63 #define STANDARDHBONDANGLEDB "Hbondangle.db" //!< default filename of typial bond angle to hydrogen database 64 64 65 65 // some values … … 68 68 69 69 70 #define UPDATECOUNT 10 70 #define UPDATECOUNT 10 //!< update ten sites per BOSSANOVA interval 71 71 72 72 #endif /*DEFS_HPP_*/ -
src/joiner.cpp
r178f92 r437922 17 17 int main(int argc, char **argv) 18 18 { 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 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 34 35 36 35 cout << "Joiner" << endl; 36 cout << "======" << endl; 37 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 38 // Get the command line options 39 if (argc < 3) { 40 cout << "Usage: " << argv[0] << " <inputdir> <prefix> [elementsdb]" << endl; 41 cout << "<inputdir>\ttherein the output of a molecuilder fragmentation is expected, each fragment with a subdir containing an energy.all and a forces.all file." << endl; 42 cout << "<prefix>\tprefix of energy and forces file." << endl; 43 cout << "[elementsdb]\tpath to elements database, needed for shieldings." << endl; 44 return 1; 45 } else { 46 dir = (char *) Malloc(sizeof(char)*(strlen(argv[2])+2), "main: *dir"); 47 strcpy(dir, "/"); 48 strcat(dir, argv[2]); 49 } 50 if (argc > 3) { 51 periode = new periodentafel; 52 periode->LoadPeriodentafel(argv[3]); 53 } 54 54 55 56 57 55 // Test the given directory 56 if (!TestParams(argc, argv)) 57 return 1; 58 58 59 59 // +++++++++++++++++ PARSING +++++++++++++++++++++++++++++++ 60 60 61 62 63 64 65 66 67 68 61 // ------------- Parse through all Fragment subdirs -------- 62 if (!Energy.ParseFragmentMatrix(argv[1], dir, EnergySuffix, 0,0)) return 1; 63 Hcorrected = Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX, 0,0); 64 if (!Force.ParseFragmentMatrix(argv[1], dir, ForcesSuffix, 0,0)) return 1; 65 if (periode != NULL) { // also look for PAS values 66 if (!Shielding.ParseFragmentMatrix(argv[1], dir, ShieldingSuffix, 1, 0)) return 1; 67 if (!ShieldingPAS.ParseFragmentMatrix(argv[1], dir, ShieldingPASSuffix, 1, 0)) return 1; 68 } 69 69 70 71 72 70 // ---------- Parse the TE Factors into an array ----------------- 71 if (!Energy.ParseIndices()) return 1; 72 if (Hcorrected) Hcorrection.ParseIndices(); 73 73 74 75 74 // ---------- Parse the Force indices into an array --------------- 75 if (!Force.ParseIndices(argv[1])) return 1; 76 76 77 78 79 80 81 77 // ---------- Parse the shielding indices into an array --------------- 78 if (periode != NULL) { // also look for PAS values 79 if(!Shielding.ParseIndices(argv[1])) return 1; 80 if(!ShieldingPAS.ParseIndices(argv[1])) return 1; 81 } 82 82 83 84 83 // ---------- Parse the KeySets into an array --------------- 84 if (!KeySet.ParseKeySets(argv[1], Force.RowCounter, Force.MatrixCounter)) return 1; 85 85 86 87 88 if (Hcorrected)HcorrectionFragments.AllocateMatrix(Hcorrection.Header, Hcorrection.MatrixCounter, Hcorrection.RowCounter, Hcorrection.ColumnCounter);89 90 91 92 93 86 if (!KeySet.ParseManyBodyTerms()) return 1; 87 if (!EnergyFragments.AllocateMatrix(Energy.Header, Energy.MatrixCounter, Energy.RowCounter, Energy.ColumnCounter)) return 1; 88 if (Hcorrected) HcorrectionFragments.AllocateMatrix(Hcorrection.Header, Hcorrection.MatrixCounter, Hcorrection.RowCounter, Hcorrection.ColumnCounter); 89 if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return 1; 90 if (periode != NULL) { // also look for PAS values 91 if (!ShieldingFragments.AllocateMatrix(Shielding.Header, Shielding.MatrixCounter, Shielding.RowCounter, Shielding.ColumnCounter)) return 1; 92 if (!ShieldingPASFragments.AllocateMatrix(ShieldingPAS.Header, ShieldingPAS.MatrixCounter, ShieldingPAS.RowCounter, ShieldingPAS.ColumnCounter)) return 1; 93 } 94 94 95 96 97 98 99 100 101 95 // ----------- Resetting last matrices (where full QM values are stored right now) 96 if(!Energy.SetLastMatrix(0., 0)) return 1; 97 if(!Force.SetLastMatrix(0., 2)) return 1; 98 if (periode != NULL) { // also look for PAS values 99 if(!Shielding.SetLastMatrix(0., 2)) return 1; 100 if(!ShieldingPAS.SetLastMatrix(0., 2)) return 1; 101 } 102 102 103 103 // +++++++++++++++++ SUMMING +++++++++++++++++++++++++++++++ 104 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 105 // --------- sum up and write for each order---------------- 106 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 107 // --------- sum up energy -------------------- 108 cout << "Summing energy of order " << BondOrder+1 << " ..." << endl; 109 if (!EnergyFragments.SumSubManyBodyTerms(Energy, KeySet, BondOrder)) return 1; 110 if (Hcorrected) { 111 HcorrectionFragments.SumSubManyBodyTerms(Hcorrection, KeySet, BondOrder); 112 if (!Energy.SumSubEnergy(EnergyFragments, &HcorrectionFragments, KeySet, BondOrder, 1.)) return 1; 113 if (Hcorrected) Hcorrection.SumSubEnergy(HcorrectionFragments, NULL, KeySet, BondOrder, 1.); 114 } else 115 if (!Energy.SumSubEnergy(EnergyFragments, NULL, KeySet, BondOrder, 1.)) return 1; 116 // --------- sum up Forces -------------------- 117 cout << "Summing forces of order " << BondOrder+1 << " ..." << endl; 118 if (!ForceFragments.SumSubManyBodyTerms(Force, KeySet, BondOrder)) return 1; 119 if (!Force.SumSubForces(ForceFragments, KeySet, BondOrder, 1.)) return 1; 120 if (periode != NULL) { // also look for PAS values 121 cout << "Summing shieldings of order " << BondOrder+1 << " ..." << endl; 122 if (!ShieldingFragments.SumSubManyBodyTerms(Shielding, KeySet, BondOrder)) return 1; 123 if (!Shielding.SumSubForces(ShieldingFragments, KeySet, BondOrder, 1.)) return 1; 124 if (!ShieldingPASFragments.SumSubManyBodyTerms(ShieldingPAS, KeySet, BondOrder)) return 1; 125 if (!ShieldingPAS.SumSubForces(ShieldingPASFragments, KeySet, BondOrder, 1.)) return 1; 126 } 127 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 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 163 164 165 166 167 168 169 170 171 164 // write last matrices as fragments into central dir (not subdir as above), for analyzer to know index bounds 165 if (!Energy.WriteLastMatrix(argv[1], dir, EnergyFragmentSuffix)) return 1; 166 if (Hcorrected) Hcorrection.WriteLastMatrix(argv[1], dir, HcorrectionFragmentSuffix); 167 if (!Force.WriteLastMatrix(argv[1], dir, ForceFragmentSuffix)) return 1; 168 if (periode != NULL) { // also look for PAS values 169 if (!Shielding.WriteLastMatrix(argv[1], dir, ShieldingFragmentSuffix)) return 1; 170 if (!ShieldingPAS.WriteLastMatrix(argv[1], dir, ShieldingPASFragmentSuffix)) return 1; 171 } 172 172 173 174 175 176 177 173 // exit 174 delete(periode); 175 Free((void **)&dir, "main: *dir"); 176 cout << "done." << endl; 177 return 0; 178 178 }; 179 179 -
src/moleculelist.cpp
r178f92 r437922 527 527 528 528 // open file for the force factors 529 *out << Verbose(1) << "Saving 529 *out << Verbose(1) << "Saving force factors ... "; 530 530 line << path << "/" << FRAGMENTPREFIX << FORCESFILE; 531 531 ForcesFile.open(line.str().c_str(), ios::out); … … 695 695 MoleculeLeafClass::MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf = NULL) 696 696 { 697 // 698 // 699 // 700 // 701 // 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; 702 702 Leaf = NULL; 703 703 previous = PreviousLeaf; … … 715 715 MoleculeLeafClass::~MoleculeLeafClass() 716 716 { 717 // 718 // 719 // 720 // 721 // 722 // 723 // 724 // 725 // 726 // 717 // if (DownLeaf != NULL) {// drop leaves further down 718 // MoleculeLeafClass *Walker = DownLeaf; 719 // MoleculeLeafClass *Next; 720 // do { 721 // Next = Walker->NextLeaf; 722 // delete(Walker); 723 // Walker = Next; 724 // } while (Walker != NULL); 725 // // Last Walker sets DownLeaf automatically to NULL 726 // } 727 727 // remove the leaf itself 728 728 if (Leaf != NULL) { … … 733 733 if (previous != NULL) 734 734 previous->next = next; 735 // 736 // 737 // NextLeaf->UpLeaf = UpLeaf;// either null as we are top level or the upleaf of the first node738 // 739 // UpLeaf->DownLeaf = NextLeaf;// either null as we are only leaf or NextLeaf if we are just the first740 // 741 // 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; 742 742 if (next != NULL) // are we last in list 743 743 next->previous = previous; -
src/molecules.cpp
r178f92 r437922 16 16 double LSQ (const gsl_vector * x, void * params) 17 17 { 18 19 20 21 22 23 24 25 26 27 28 18 double sum = 0.; 19 struct LSQ_params *par = (struct LSQ_params *)params; 20 Vector **vectors = par->vectors; 21 int num = par->num; 22 23 for (int i=num;i--;) { 24 for(int j=NDIM;j--;) 25 sum += (gsl_vector_get(x,j) - (vectors[i])->x[j])*(gsl_vector_get(x,j) - (vectors[i])->x[j]); 26 } 27 28 return sum; 29 29 }; 30 30 … … 36 36 molecule::molecule(periodentafel *teil) 37 37 { 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 38 // init atom chain list 39 start = new atom; 40 end = new atom; 41 start->father = NULL; 42 end->father = NULL; 43 link(start,end); 44 // init bond chain list 45 first = new bond(start, end, 1, -1); 46 last = new bond(start, end, 1, -1); 47 link(first,last); 48 // other stuff 49 MDSteps = 0; 50 last_atom = 0; 51 elemente = teil; 52 AtomCount = 0; 53 BondCount = 0; 54 NoNonBonds = 0; 55 NoNonHydrogen = 0; 56 NoCyclicBonds = 0; 57 ListOfBondsPerAtom = NULL; 58 NumberOfBondsPerAtom = NULL; 59 ElementCount = 0; 60 for(int i=MAX_ELEMENTS;i--;) 61 ElementsInMolecule[i] = 0; 62 cell_size[0] = cell_size[2] = cell_size[5]= 20.; 63 cell_size[1] = cell_size[3] = cell_size[4]= 0.; 64 strcpy(name,"none"); 65 IndexNr = -1; 66 ActiveFlag = false; 67 67 }; 68 68 … … 72 72 molecule::~molecule() 73 73 { 74 75 76 77 78 79 80 81 82 83 74 if (ListOfBondsPerAtom != NULL) 75 for(int i=AtomCount;i--;) 76 Free((void **)&ListOfBondsPerAtom[i], "molecule::~molecule: ListOfBondsPerAtom[i]"); 77 Free((void **)&ListOfBondsPerAtom, "molecule::~molecule: ListOfBondsPerAtom"); 78 Free((void **)&NumberOfBondsPerAtom, "molecule::~molecule: NumberOfBondsPerAtom"); 79 CleanupMolecule(); 80 delete(first); 81 delete(last); 82 delete(end); 83 delete(start); 84 84 }; 85 85 … … 91 91 bool molecule::AddAtom(atom *pointer) 92 92 { 93 94 95 pointer->nr = last_atom++;// increase number within molecule96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 93 if (pointer != NULL) { 94 pointer->sort = &pointer->nr; 95 pointer->nr = last_atom++; // increase number within molecule 96 AtomCount++; 97 if (pointer->type != NULL) { 98 if (ElementsInMolecule[pointer->type->Z] == 0) 99 ElementCount++; 100 ElementsInMolecule[pointer->type->Z]++; // increase number of elements 101 if (pointer->type->Z != 1) 102 NoNonHydrogen++; 103 if (pointer->Name == NULL) { 104 Free((void **)&pointer->Name, "molecule::AddAtom: *pointer->Name"); 105 pointer->Name = (char *) Malloc(sizeof(char)*6, "molecule::AddAtom: *pointer->Name"); 106 sprintf(pointer->Name, "%2s%02d", pointer->type->symbol, pointer->nr+1); 107 } 108 } 109 return add(pointer, end); 110 } else 111 return false; 112 112 }; 113 113 … … 119 119 atom * molecule::AddCopyAtom(atom *pointer) 120 120 { 121 122 123 walker->type = pointer->type;// copy element of atom124 125 126 127 128 walker->nr = last_atom++;// increase number within molecule129 130 131 132 133 134 135 136 137 138 121 if (pointer != NULL) { 122 atom *walker = new atom(); 123 walker->type = pointer->type; // copy element of atom 124 walker->x.CopyVector(&pointer->x); // copy coordination 125 walker->v.CopyVector(&pointer->v); // copy velocity 126 walker->FixedIon = pointer->FixedIon; 127 walker->sort = &walker->nr; 128 walker->nr = last_atom++; // increase number within molecule 129 walker->father = pointer; //->GetTrueFather(); 130 walker->Name = (char *) Malloc(sizeof(char)*strlen(pointer->Name)+1, "molecule::AddCopyAtom: *Name"); 131 strcpy (walker->Name, pointer->Name); 132 add(walker, end); 133 if ((pointer->type != NULL) && (pointer->type->Z != 1)) 134 NoNonHydrogen++; 135 AtomCount++; 136 return walker; 137 } else 138 return NULL; 139 139 }; 140 140 … … 144 144 * -# Single Bond: Simply add new atom with bond distance rescaled to typical hydrogen one 145 145 * -# Double Bond: Here, we need the **BondList of the \a *origin atom, by scanning for the other bonds instead of 146 * 147 * 148 * 149 * 150 * 146 * *Bond, we use the through these connected atoms to determine the plane they lie in, vector::MakeNormalvector(). 147 * The orthonormal vector to this plane along with the vector in *Bond direction determines the plane the two 148 * replacing hydrogens shall lie in. Now, all remains to do is take the usual hydrogen double bond angle for the 149 * element of *origin and form the sin/cos admixture of both plane vectors for the new coordinates of the two 150 * hydrogens forming this angle with *origin. 151 151 * -# Triple Bond: The idea is to set up a tetraoid (C1-H1-H2-H3) (however the lengths \f$b\f$ of the sides of the base 152 * 153 * 154 * 155 * 156 * 157 * 158 * 159 * 160 * 161 * 162 * 163 * 164 * 152 * triangle formed by the to be added hydrogens are not equal to the typical bond distance \f$l\f$ but have to be 153 * determined from the typical angle \f$\alpha\f$ for a hydrogen triple connected to the element of *origin): 154 * We have the height \f$d\f$ as the vector in *Bond direction (from triangle C1-H1-H2). 155 * \f[ h = l \cdot \cos{\left (\frac{\alpha}{2} \right )} \qquad b = 2l \cdot \sin{\left (\frac{\alpha}{2} \right)} \quad \rightarrow \quad d = l \cdot \sqrt{\cos^2{\left (\frac{\alpha}{2} \right)}-\frac{1}{3}\cdot\sin^2{\left (\frac{\alpha}{2}\right )}} 156 * \f] 157 * vector::GetNormalvector() creates one orthonormal vector from this *Bond vector and vector::MakeNormalvector creates 158 * the third one from the former two vectors. The latter ones form the plane of the base triangle mentioned above. 159 * The lengths for these are \f$f\f$ and \f$g\f$ (from triangle H1-H2-(center of H1-H2-H3)) with knowledge that 160 * the median lines in an isosceles triangle meet in the center point with a ratio 2:1. 161 * \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2} 162 * \f] 163 * as the coordination of all three atoms in the coordinate system of these three vectors: 164 * \f$\pmatrix{d & f & 0}\f$, \f$\pmatrix{d & -0.5 \cdot f & g}\f$ and \f$\pmatrix{d & -0.5 \cdot f & -g}\f$. 165 165 * 166 166 * \param *out output stream for debugging … … 170 170 * \param *replacement pointer to the atom which shall be copied as a hydrogen atom in this molecule 171 171 * \param **BondList list of bonds \a *replacement has (necessary to determine plane for double and triple bonds) 172 * \param NumBond 172 * \param NumBond number of bonds in \a **BondList 173 173 * \param isAngstroem whether the coordination of the given atoms is in AtomicLength (false) or Angstrom(true) 174 174 * \return number of atoms added, if < bond::BondDegree then something went wrong … … 177 177 bool molecule::AddHydrogenReplacementAtom(ofstream *out, bond *TopBond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem) 178 178 { 179 double bondlength;// bond length of the bond to be replaced/cut180 double bondangle;// bond angle of the bond to be replaced/cut181 double BondRescale;// rescale value for the hydrogen bond length182 bool AllWentWell = true;// flag gathering the boolean return value of molecule::AddAtom and other functions, as return value on exit183 184 185 double b,l,d,f,g, alpha, factors[NDIM];// hold temporary values in triple bond case for coordination determination186 Vector Orthovector1, Orthovector2;// temporary vectors in coordination construction187 Vector InBondvector;// vector in direction of *Bond188 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 FirstOtherAtom = new atom();// new atom237 FirstOtherAtom->type = elemente->FindElement(1);// element is Hydrogen238 239 240 241 242 243 244 FirstOtherAtom->father = NULL;// if we replace hydrogen, we mark it as our father, otherwise we are just an added hydrogen with no father245 246 InBondvector.Scale(&BondRescale);// rescale the distance vector to Hydrogen bond length247 248 FirstOtherAtom->x.AddVector(&InBondvector);// ... and add distance vector to replacement atom249 250 // 251 // 252 // 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 if (SecondOtherAtom == NULL) {// then we have an atom with valence four, but only 3 bonds: one to replace and one which is TopBond (third is FirstBond)273 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 FirstOtherAtom->father = NULL;// we are just an added hydrogen with no father302 SecondOtherAtom->father = NULL; //we are just an added hydrogen with no father303 304 305 306 307 308 309 310 // 311 // 312 // 313 // 314 // 315 // 316 // 317 318 319 320 321 322 323 FirstOtherAtom->x.Scale(&BondRescale);// rescale by correct BondDistance324 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 FirstOtherAtom->father = NULL; //we are just an added hydrogen with no father361 SecondOtherAtom->father = NULL; //we are just an added hydrogen with no father362 ThirdOtherAtom->father = NULL; //we are just an added hydrogen with no father363 364 365 366 // 367 // 368 // 369 370 // 371 // 372 // 373 374 375 alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.;// retrieve triple bond angle from database376 l = BondRescale;// desired bond length377 b = 2.*l*sin(alpha);// base length of isosceles triangle378 d = l*sqrt(cos(alpha)*cos(alpha) - sin(alpha)*sin(alpha)/3.);// length for InBondvector379 f = b/sqrt(3.);// length for Orthvector1380 g = b/2.;// length for Orthvector2381 // 382 // *out << Verbose(3) << "The three Bond lengths: " << sqrt(d*d+f*f) << ", " << sqrt(d*d+(-0.5*f)*(-0.5*f)+g*g) << ", "<< sqrt(d*d+(-0.5*f)*(-0.5*f)+g*g) << endl;383 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 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 // 433 179 double bondlength; // bond length of the bond to be replaced/cut 180 double bondangle; // bond angle of the bond to be replaced/cut 181 double BondRescale; // rescale value for the hydrogen bond length 182 bool AllWentWell = true; // flag gathering the boolean return value of molecule::AddAtom and other functions, as return value on exit 183 bond *FirstBond = NULL, *SecondBond = NULL; // Other bonds in double bond case to determine "other" plane 184 atom *FirstOtherAtom = NULL, *SecondOtherAtom = NULL, *ThirdOtherAtom = NULL; // pointer to hydrogen atoms to be added 185 double b,l,d,f,g, alpha, factors[NDIM]; // hold temporary values in triple bond case for coordination determination 186 Vector Orthovector1, Orthovector2; // temporary vectors in coordination construction 187 Vector InBondvector; // vector in direction of *Bond 188 bond *Binder = NULL; 189 double *matrix; 190 191 // *out << Verbose(3) << "Begin of AddHydrogenReplacementAtom." << endl; 192 // create vector in direction of bond 193 InBondvector.CopyVector(&TopReplacement->x); 194 InBondvector.SubtractVector(&TopOrigin->x); 195 bondlength = InBondvector.Norm(); 196 197 // is greater than typical bond distance? Then we have to correct periodically 198 // the problem is not the H being out of the box, but InBondvector have the wrong direction 199 // due to TopReplacement or Origin being on the wrong side! 200 if (bondlength > BondDistance) { 201 // *out << Verbose(4) << "InBondvector is: "; 202 // InBondvector.Output(out); 203 // *out << endl; 204 Orthovector1.Zero(); 205 for (int i=NDIM;i--;) { 206 l = TopReplacement->x.x[i] - TopOrigin->x.x[i]; 207 if (fabs(l) > BondDistance) { // is component greater than bond distance 208 Orthovector1.x[i] = (l < 0) ? -1. : +1.; 209 } // (signs are correct, was tested!) 210 } 211 matrix = ReturnFullMatrixforSymmetric(cell_size); 212 Orthovector1.MatrixMultiplication(matrix); 213 InBondvector.SubtractVector(&Orthovector1); // subtract just the additional translation 214 Free((void **)&matrix, "molecule::AddHydrogenReplacementAtom: *matrix"); 215 bondlength = InBondvector.Norm(); 216 // *out << Verbose(4) << "Corrected InBondvector is now: "; 217 // InBondvector.Output(out); 218 // *out << endl; 219 } // periodic correction finished 220 221 InBondvector.Normalize(); 222 // get typical bond length and store as scale factor for later 223 BondRescale = TopOrigin->type->HBondDistance[TopBond->BondDegree-1]; 224 if (BondRescale == -1) { 225 cerr << Verbose(3) << "ERROR: There is no typical hydrogen bond distance in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 226 return false; 227 BondRescale = bondlength; 228 } else { 229 if (!IsAngstroem) 230 BondRescale /= (1.*AtomicLengthToAngstroem); 231 } 232 233 // discern single, double and triple bonds 234 switch(TopBond->BondDegree) { 235 case 1: 236 FirstOtherAtom = new atom(); // new atom 237 FirstOtherAtom->type = elemente->FindElement(1); // element is Hydrogen 238 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 239 FirstOtherAtom->FixedIon = TopReplacement->FixedIon; 240 if (TopReplacement->type->Z == 1) { // neither rescale nor replace if it's already hydrogen 241 FirstOtherAtom->father = TopReplacement; 242 BondRescale = bondlength; 243 } else { 244 FirstOtherAtom->father = NULL; // if we replace hydrogen, we mark it as our father, otherwise we are just an added hydrogen with no father 245 } 246 InBondvector.Scale(&BondRescale); // rescale the distance vector to Hydrogen bond length 247 FirstOtherAtom->x.CopyVector(&TopOrigin->x); // set coordination to origin ... 248 FirstOtherAtom->x.AddVector(&InBondvector); // ... and add distance vector to replacement atom 249 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom); 250 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: "; 251 // FirstOtherAtom->x.Output(out); 252 // *out << endl; 253 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1); 254 Binder->Cyclic = false; 255 Binder->Type = TreeEdge; 256 break; 257 case 2: 258 // determine two other bonds (warning if there are more than two other) plus valence sanity check 259 for (int i=0;i<NumBond;i++) { 260 if (BondList[i] != TopBond) { 261 if (FirstBond == NULL) { 262 FirstBond = BondList[i]; 263 FirstOtherAtom = BondList[i]->GetOtherAtom(TopOrigin); 264 } else if (SecondBond == NULL) { 265 SecondBond = BondList[i]; 266 SecondOtherAtom = BondList[i]->GetOtherAtom(TopOrigin); 267 } else { 268 *out << Verbose(3) << "WARNING: Detected more than four bonds for atom " << TopOrigin->Name; 269 } 270 } 271 } 272 if (SecondOtherAtom == NULL) { // then we have an atom with valence four, but only 3 bonds: one to replace and one which is TopBond (third is FirstBond) 273 SecondBond = TopBond; 274 SecondOtherAtom = TopReplacement; 275 } 276 if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all 277 // *out << Verbose(3) << "Regarding the double bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") to be constructed: Taking " << FirstOtherAtom->Name << " and " << SecondOtherAtom->Name << " along with " << TopOrigin->Name << " to determine orthogonal plane." << endl; 278 279 // determine the plane of these two with the *origin 280 AllWentWell = AllWentWell && Orthovector1.MakeNormalVector(&TopOrigin->x, &FirstOtherAtom->x, &SecondOtherAtom->x); 281 } else { 282 Orthovector1.GetOneNormalVector(&InBondvector); 283 } 284 //*out << Verbose(3)<< "Orthovector1: "; 285 //Orthovector1.Output(out); 286 //*out << endl; 287 // orthogonal vector and bond vector between origin and replacement form the new plane 288 Orthovector1.MakeNormalVector(&InBondvector); 289 Orthovector1.Normalize(); 290 //*out << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl; 291 292 // create the two Hydrogens ... 293 FirstOtherAtom = new atom(); 294 SecondOtherAtom = new atom(); 295 FirstOtherAtom->type = elemente->FindElement(1); 296 SecondOtherAtom->type = elemente->FindElement(1); 297 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 298 FirstOtherAtom->FixedIon = TopReplacement->FixedIon; 299 SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 300 SecondOtherAtom->FixedIon = TopReplacement->FixedIon; 301 FirstOtherAtom->father = NULL; // we are just an added hydrogen with no father 302 SecondOtherAtom->father = NULL; // we are just an added hydrogen with no father 303 bondangle = TopOrigin->type->HBondAngle[1]; 304 if (bondangle == -1) { 305 *out << Verbose(3) << "ERROR: There is no typical hydrogen bond angle in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 306 return false; 307 bondangle = 0; 308 } 309 bondangle *= M_PI/180./2.; 310 // *out << Verbose(3) << "ReScaleCheck: InBondvector "; 311 // InBondvector.Output(out); 312 // *out << endl; 313 // *out << Verbose(3) << "ReScaleCheck: Orthovector "; 314 // Orthovector1.Output(out); 315 // *out << endl; 316 // *out << Verbose(3) << "Half the bond angle is " << bondangle << ", sin and cos of it: " << sin(bondangle) << ", " << cos(bondangle) << endl; 317 FirstOtherAtom->x.Zero(); 318 SecondOtherAtom->x.Zero(); 319 for(int i=NDIM;i--;) { // rotate by half the bond angle in both directions (InBondvector is bondangle = 0 direction) 320 FirstOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (sin(bondangle)); 321 SecondOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (-sin(bondangle)); 322 } 323 FirstOtherAtom->x.Scale(&BondRescale); // rescale by correct BondDistance 324 SecondOtherAtom->x.Scale(&BondRescale); 325 //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl; 326 for(int i=NDIM;i--;) { // and make relative to origin atom 327 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i]; 328 SecondOtherAtom->x.x[i] += TopOrigin->x.x[i]; 329 } 330 // ... and add to molecule 331 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom); 332 AllWentWell = AllWentWell && AddAtom(SecondOtherAtom); 333 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: "; 334 // FirstOtherAtom->x.Output(out); 335 // *out << endl; 336 // *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: "; 337 // SecondOtherAtom->x.Output(out); 338 // *out << endl; 339 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1); 340 Binder->Cyclic = false; 341 Binder->Type = TreeEdge; 342 Binder = AddBond(BottomOrigin, SecondOtherAtom, 1); 343 Binder->Cyclic = false; 344 Binder->Type = TreeEdge; 345 break; 346 case 3: 347 // take the "usual" tetraoidal angle and add the three Hydrogen in direction of the bond (height of the tetraoid) 348 FirstOtherAtom = new atom(); 349 SecondOtherAtom = new atom(); 350 ThirdOtherAtom = new atom(); 351 FirstOtherAtom->type = elemente->FindElement(1); 352 SecondOtherAtom->type = elemente->FindElement(1); 353 ThirdOtherAtom->type = elemente->FindElement(1); 354 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 355 FirstOtherAtom->FixedIon = TopReplacement->FixedIon; 356 SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 357 SecondOtherAtom->FixedIon = TopReplacement->FixedIon; 358 ThirdOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 359 ThirdOtherAtom->FixedIon = TopReplacement->FixedIon; 360 FirstOtherAtom->father = NULL; // we are just an added hydrogen with no father 361 SecondOtherAtom->father = NULL; // we are just an added hydrogen with no father 362 ThirdOtherAtom->father = NULL; // we are just an added hydrogen with no father 363 364 // we need to vectors orthonormal the InBondvector 365 AllWentWell = AllWentWell && Orthovector1.GetOneNormalVector(&InBondvector); 366 // *out << Verbose(3) << "Orthovector1: "; 367 // Orthovector1.Output(out); 368 // *out << endl; 369 AllWentWell = AllWentWell && Orthovector2.MakeNormalVector(&InBondvector, &Orthovector1); 370 // *out << Verbose(3) << "Orthovector2: "; 371 // Orthovector2.Output(out); 372 // *out << endl; 373 374 // create correct coordination for the three atoms 375 alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.; // retrieve triple bond angle from database 376 l = BondRescale; // desired bond length 377 b = 2.*l*sin(alpha); // base length of isosceles triangle 378 d = l*sqrt(cos(alpha)*cos(alpha) - sin(alpha)*sin(alpha)/3.); // length for InBondvector 379 f = b/sqrt(3.); // length for Orthvector1 380 g = b/2.; // length for Orthvector2 381 // *out << Verbose(3) << "Bond length and half-angle: " << l << ", " << alpha << "\t (b,d,f,g) = " << b << ", " << d << ", " << f << ", " << g << ", " << endl; 382 // *out << Verbose(3) << "The three Bond lengths: " << sqrt(d*d+f*f) << ", " << sqrt(d*d+(-0.5*f)*(-0.5*f)+g*g) << ", " << sqrt(d*d+(-0.5*f)*(-0.5*f)+g*g) << endl; 383 factors[0] = d; 384 factors[1] = f; 385 factors[2] = 0.; 386 FirstOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 387 factors[1] = -0.5*f; 388 factors[2] = g; 389 SecondOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 390 factors[2] = -g; 391 ThirdOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 392 393 // rescale each to correct BondDistance 394 // FirstOtherAtom->x.Scale(&BondRescale); 395 // SecondOtherAtom->x.Scale(&BondRescale); 396 // ThirdOtherAtom->x.Scale(&BondRescale); 397 398 // and relative to *origin atom 399 FirstOtherAtom->x.AddVector(&TopOrigin->x); 400 SecondOtherAtom->x.AddVector(&TopOrigin->x); 401 ThirdOtherAtom->x.AddVector(&TopOrigin->x); 402 403 // ... and add to molecule 404 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom); 405 AllWentWell = AllWentWell && AddAtom(SecondOtherAtom); 406 AllWentWell = AllWentWell && AddAtom(ThirdOtherAtom); 407 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: "; 408 // FirstOtherAtom->x.Output(out); 409 // *out << endl; 410 // *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: "; 411 // SecondOtherAtom->x.Output(out); 412 // *out << endl; 413 // *out << Verbose(4) << "Added " << *ThirdOtherAtom << " at: "; 414 // ThirdOtherAtom->x.Output(out); 415 // *out << endl; 416 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1); 417 Binder->Cyclic = false; 418 Binder->Type = TreeEdge; 419 Binder = AddBond(BottomOrigin, SecondOtherAtom, 1); 420 Binder->Cyclic = false; 421 Binder->Type = TreeEdge; 422 Binder = AddBond(BottomOrigin, ThirdOtherAtom, 1); 423 Binder->Cyclic = false; 424 Binder->Type = TreeEdge; 425 break; 426 default: 427 cerr << "ERROR: BondDegree does not state single, double or triple bond!" << endl; 428 AllWentWell = false; 429 break; 430 } 431 432 // *out << Verbose(3) << "End of AddHydrogenReplacementAtom." << endl; 433 return AllWentWell; 434 434 }; 435 435 … … 441 441 bool molecule::AddXYZFile(string filename) 442 442 { 443 444 445 446 atom *Walker = NULL;// pointer to added atom447 char shorthand[3];// shorthand for atom name448 ifstream xyzfile;// xyz file449 string line;// currently parsed line450 double x[3];// atom coordinates451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 AddAtom(Walker);// add to molecule492 493 494 495 496 443 istringstream *input = NULL; 444 int NumberOfAtoms = 0; // atom number in xyz read 445 int i, j; // loop variables 446 atom *Walker = NULL; // pointer to added atom 447 char shorthand[3]; // shorthand for atom name 448 ifstream xyzfile; // xyz file 449 string line; // currently parsed line 450 double x[3]; // atom coordinates 451 452 xyzfile.open(filename.c_str()); 453 if (!xyzfile) 454 return false; 455 456 getline(xyzfile,line,'\n'); // Read numer of atoms in file 457 input = new istringstream(line); 458 *input >> NumberOfAtoms; 459 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl; 460 getline(xyzfile,line,'\n'); // Read comment 461 cout << Verbose(1) << "Comment: " << line << endl; 462 463 if (MDSteps == 0) // no atoms yet present 464 MDSteps++; 465 for(i=0;i<NumberOfAtoms;i++){ 466 Walker = new atom; 467 getline(xyzfile,line,'\n'); 468 istringstream *item = new istringstream(line); 469 //istringstream input(line); 470 //cout << Verbose(1) << "Reading: " << line << endl; 471 *item >> shorthand; 472 *item >> x[0]; 473 *item >> x[1]; 474 *item >> x[2]; 475 Walker->type = elemente->FindElement(shorthand); 476 if (Walker->type == NULL) { 477 cerr << "Could not parse the element at line: '" << line << "', setting to H."; 478 Walker->type = elemente->FindElement(1); 479 } 480 if (Trajectories[Walker].R.size() <= (unsigned int)MDSteps) { 481 Trajectories[Walker].R.resize(MDSteps+10); 482 Trajectories[Walker].U.resize(MDSteps+10); 483 Trajectories[Walker].F.resize(MDSteps+10); 484 } 485 for(j=NDIM;j--;) { 486 Walker->x.x[j] = x[j]; 487 Trajectories[Walker].R.at(MDSteps-1).x[j] = x[j]; 488 Trajectories[Walker].U.at(MDSteps-1).x[j] = 0; 489 Trajectories[Walker].F.at(MDSteps-1).x[j] = 0; 490 } 491 AddAtom(Walker); // add to molecule 492 delete(item); 493 } 494 xyzfile.close(); 495 delete(input); 496 return true; 497 497 }; 498 498 … … 502 502 molecule *molecule::CopyMolecule() 503 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 if (Walker->father->father == Walker->father)// same atom in copy's father points to itself545 Walker->father = Walker;// set father to itself (copy of a whole molecule)546 547 Walker->father = Walker->father->father;// set father to original's father548 549 550 551 552 if (first->next != last) {// if adjaceny list is present553 554 555 556 557 504 molecule *copy = new molecule(elemente); 505 atom *CurrentAtom = NULL; 506 atom *LeftAtom = NULL, *RightAtom = NULL; 507 atom *Walker = NULL; 508 509 // copy all atoms 510 Walker = start; 511 while(Walker->next != end) { 512 Walker = Walker->next; 513 CurrentAtom = copy->AddCopyAtom(Walker); 514 } 515 516 // copy all bonds 517 bond *Binder = first; 518 bond *NewBond = NULL; 519 while(Binder->next != last) { 520 Binder = Binder->next; 521 // get the pendant atoms of current bond in the copy molecule 522 LeftAtom = copy->start; 523 while (LeftAtom->next != copy->end) { 524 LeftAtom = LeftAtom->next; 525 if (LeftAtom->father == Binder->leftatom) 526 break; 527 } 528 RightAtom = copy->start; 529 while (RightAtom->next != copy->end) { 530 RightAtom = RightAtom->next; 531 if (RightAtom->father == Binder->rightatom) 532 break; 533 } 534 NewBond = copy->AddBond(LeftAtom, RightAtom, Binder->BondDegree); 535 NewBond->Cyclic = Binder->Cyclic; 536 if (Binder->Cyclic) 537 copy->NoCyclicBonds++; 538 NewBond->Type = Binder->Type; 539 } 540 // correct fathers 541 Walker = copy->start; 542 while(Walker->next != copy->end) { 543 Walker = Walker->next; 544 if (Walker->father->father == Walker->father) // same atom in copy's father points to itself 545 Walker->father = Walker; // set father to itself (copy of a whole molecule) 546 else 547 Walker->father = Walker->father->father; // set father to original's father 548 } 549 // copy values 550 copy->CountAtoms((ofstream *)&cout); 551 copy->CountElements(); 552 if (first->next != last) { // if adjaceny list is present 553 copy->BondDistance = BondDistance; 554 copy->CreateListOfBondsPerAtom((ofstream *)&cout); 555 } 556 557 return copy; 558 558 }; 559 559 … … 566 566 bond * molecule::AddBond(atom *atom1, atom *atom2, int degree=1) 567 567 { 568 569 570 571 572 573 574 575 576 577 568 bond *Binder = NULL; 569 if ((atom1 != NULL) && (FindAtom(atom1->nr) != NULL) && (atom2 != NULL) && (FindAtom(atom2->nr) != NULL)) { 570 Binder = new bond(atom1, atom2, degree, BondCount++); 571 if ((atom1->type != NULL) && (atom1->type->Z != 1) && (atom2->type != NULL) && (atom2->type->Z != 1)) 572 NoNonBonds++; 573 add(Binder, last); 574 } else { 575 cerr << Verbose(1) << "ERROR: Could not add bond between " << atom1->Name << " and " << atom2->Name << " as one or both are not present in the molecule." << endl; 576 } 577 return Binder; 578 578 }; 579 579 … … 585 585 bool molecule::RemoveBond(bond *pointer) 586 586 { 587 588 589 587 //cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl; 588 removewithoutcheck(pointer); 589 return true; 590 590 }; 591 591 … … 597 597 bool molecule::RemoveBonds(atom *BondPartner) 598 598 { 599 600 599 cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl; 600 return false; 601 601 }; 602 602 … … 622 622 void molecule::SetBoxDimension(Vector *dim) 623 623 { 624 625 626 627 628 629 624 cell_size[0] = dim->x[0]; 625 cell_size[1] = 0.; 626 cell_size[2] = dim->x[1]; 627 cell_size[3] = 0.; 628 cell_size[4] = 0.; 629 cell_size[5] = dim->x[2]; 630 630 }; 631 631 … … 636 636 bool molecule::CenterInBox(ofstream *out, Vector *BoxLengths) 637 637 { 638 639 640 641 642 643 644 ptr = start->next;// start at first in list645 if (ptr != end) {//list not empty?646 647 648 649 650 while (ptr->next != end) {// continue with second if present651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 else {// else center in box668 669 670 671 638 bool status = true; 639 atom *ptr = NULL; 640 Vector *min = new Vector; 641 Vector *max = new Vector; 642 643 // gather min and max for each axis 644 ptr = start->next; // start at first in list 645 if (ptr != end) { //list not empty? 646 for (int i=NDIM;i--;) { 647 max->x[i] = ptr->x.x[i]; 648 min->x[i] = ptr->x.x[i]; 649 } 650 while (ptr->next != end) { // continue with second if present 651 ptr = ptr->next; 652 //ptr->Output(1,1,out); 653 for (int i=NDIM;i--;) { 654 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i]; 655 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i]; 656 } 657 } 658 } 659 // sanity check 660 for(int i=NDIM;i--;) { 661 if (max->x[i] - min->x[i] > BoxLengths->x[i]) 662 status = false; 663 } 664 // warn if check failed 665 if (!status) 666 *out << "WARNING: molecule is bigger than defined box!" << endl; 667 else { // else center in box 668 max->AddVector(min); 669 max->Scale(-1.); 670 max->AddVector(BoxLengths); 671 max->Scale(0.5); 672 672 Translate(max); 673 673 Center.Zero(); 674 675 676 677 678 679 674 } 675 676 // free and exit 677 delete(min); 678 delete(max); 679 return status; 680 680 }; 681 681 … … 686 686 void molecule::CenterEdge(ofstream *out, Vector *max) 687 687 { 688 689 690 // 691 atom *ptr = start->next;// start at first in list692 if (ptr != end) {//list not empty?693 694 695 696 697 while (ptr->next != end) {// continue with second if present698 699 700 701 702 703 704 705 // 706 // 707 // 708 // 709 // 710 711 712 713 714 715 716 // 688 Vector *min = new Vector; 689 690 // *out << Verbose(3) << "Begin of CenterEdge." << endl; 691 atom *ptr = start->next; // start at first in list 692 if (ptr != end) { //list not empty? 693 for (int i=NDIM;i--;) { 694 max->x[i] = ptr->x.x[i]; 695 min->x[i] = ptr->x.x[i]; 696 } 697 while (ptr->next != end) { // continue with second if present 698 ptr = ptr->next; 699 //ptr->Output(1,1,out); 700 for (int i=NDIM;i--;) { 701 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i]; 702 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i]; 703 } 704 } 705 // *out << Verbose(4) << "Maximum is "; 706 // max->Output(out); 707 // *out << ", Minimum is "; 708 // min->Output(out); 709 // *out << endl; 710 min->Scale(-1.); 711 max->AddVector(min); 712 Translate(min); 713 Center.Zero(); 714 } 715 delete(min); 716 // *out << Verbose(3) << "End of CenterEdge." << endl; 717 717 }; 718 718 … … 723 723 void molecule::CenterOrigin(ofstream *out) 724 724 { 725 726 atom *ptr = start->next;// start at first in list727 728 729 730 if (ptr != end) {//list not empty?731 while (ptr->next != end) {// continue with second if present732 733 734 735 736 737 738 739 725 int Num = 0; 726 atom *ptr = start->next; // start at first in list 727 728 Center.Zero(); 729 730 if (ptr != end) { //list not empty? 731 while (ptr->next != end) { // continue with second if present 732 ptr = ptr->next; 733 Num++; 734 Center.AddVector(&ptr->x); 735 } 736 Center.Scale(-1./Num); // divide through total number (and sign for direction) 737 Translate(&Center); 738 Center.Zero(); 739 } 740 740 }; 741 741 … … 746 746 Vector * molecule::DetermineCenterOfAll(ofstream *out) 747 747 { 748 atom *ptr = start->next;// start at first in list749 750 751 752 753 754 755 if (ptr != end) {//list not empty?756 while (ptr->next != end) {// continue with second if present757 758 759 760 761 762 763 764 765 766 767 748 atom *ptr = start->next; // start at first in list 749 Vector *a = new Vector(); 750 Vector tmp; 751 double Num = 0; 752 753 a->Zero(); 754 755 if (ptr != end) { //list not empty? 756 while (ptr->next != end) { // continue with second if present 757 ptr = ptr->next; 758 Num += 1.; 759 tmp.CopyVector(&ptr->x); 760 a->AddVector(&tmp); 761 } 762 a->Scale(-1./Num); // divide through total mass (and sign for direction) 763 } 764 //cout << Verbose(1) << "Resulting center of gravity: "; 765 //a->Output(out); 766 //cout << endl; 767 return a; 768 768 }; 769 769 … … 774 774 Vector * molecule::DetermineCenterOfGravity(ofstream *out) 775 775 { 776 atom *ptr = start->next;// start at first in list777 778 779 780 781 782 783 if (ptr != end) {//list not empty?784 while (ptr->next != end) {// continue with second if present785 786 787 788 tmp.Scale(ptr->type->mass);// scale by mass789 790 791 792 793 // 794 // 795 // 796 776 atom *ptr = start->next; // start at first in list 777 Vector *a = new Vector(); 778 Vector tmp; 779 double Num = 0; 780 781 a->Zero(); 782 783 if (ptr != end) { //list not empty? 784 while (ptr->next != end) { // continue with second if present 785 ptr = ptr->next; 786 Num += ptr->type->mass; 787 tmp.CopyVector(&ptr->x); 788 tmp.Scale(ptr->type->mass); // scale by mass 789 a->AddVector(&tmp); 790 } 791 a->Scale(-1./Num); // divide through total mass (and sign for direction) 792 } 793 // *out << Verbose(1) << "Resulting center of gravity: "; 794 // a->Output(out); 795 // *out << endl; 796 return a; 797 797 }; 798 798 … … 803 803 void molecule::CenterPeriodic(ofstream *out) 804 804 { 805 805 DeterminePeriodicCenter(Center); 806 806 }; 807 807 … … 820 820 void molecule::Scale(double **factor) 821 821 { 822 823 824 825 826 827 828 829 822 atom *ptr = start; 823 824 while (ptr->next != end) { 825 ptr = ptr->next; 826 for (int j=0;j<MDSteps;j++) 827 Trajectories[ptr].R.at(j).Scale(factor); 828 ptr->x.Scale(factor); 829 } 830 830 }; 831 831 … … 835 835 void molecule::Translate(const Vector *trans) 836 836 { 837 838 839 840 841 842 843 844 837 atom *ptr = start; 838 839 while (ptr->next != end) { 840 ptr = ptr->next; 841 for (int j=0;j<MDSteps;j++) 842 Trajectories[ptr].R.at(j).Translate(trans); 843 ptr->x.Translate(trans); 844 } 845 845 }; 846 846 … … 850 850 void molecule::Mirror(const Vector *n) 851 851 { 852 853 854 855 856 857 858 859 852 atom *ptr = start; 853 854 while (ptr->next != end) { 855 ptr = ptr->next; 856 for (int j=0;j<MDSteps;j++) 857 Trajectories[ptr].R.at(j).Mirror(n); 858 ptr->x.Mirror(n); 859 } 860 860 }; 861 861 … … 865 865 void molecule::DeterminePeriodicCenter(Vector ¢er) 866 866 { 867 868 869 870 871 872 873 874 875 876 877 878 867 atom *Walker = start; 868 bond *Binder = NULL; 869 double *matrix = ReturnFullMatrixforSymmetric(cell_size); 870 double tmp; 871 bool flag; 872 Vector Testvector, Translationvector; 873 874 do { 875 center.Zero(); 876 flag = true; 877 while (Walker->next != end) { 878 Walker = Walker->next; 879 879 #ifdef ADDHYDROGEN 880 880 if (Walker->type->Z != 1) { 881 881 #endif 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 882 Testvector.CopyVector(&Walker->x); 883 Testvector.InverseMatrixMultiplication(matrix); 884 Translationvector.Zero(); 885 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) { 886 Binder = ListOfBondsPerAtom[Walker->nr][i]; 887 if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing 888 for (int j=0;j<NDIM;j++) { 889 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j]; 890 if ((fabs(tmp)) > BondDistance) { 891 flag = false; 892 cout << Verbose(0) << "Hit: atom " << Walker->Name << " in bond " << *Binder << " has to be shifted due to " << tmp << "." << endl; 893 if (tmp > 0) 894 Translationvector.x[j] -= 1.; 895 else 896 Translationvector.x[j] += 1.; 897 } 898 } 899 } 900 Testvector.AddVector(&Translationvector); 901 Testvector.MatrixMultiplication(matrix); 902 center.AddVector(&Testvector); 903 cout << Verbose(1) << "vector is: "; 904 Testvector.Output((ofstream *)&cout); 905 cout << endl; 906 906 #ifdef ADDHYDROGEN 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 907 // now also change all hydrogens 908 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) { 909 Binder = ListOfBondsPerAtom[Walker->nr][i]; 910 if (Binder->GetOtherAtom(Walker)->type->Z == 1) { 911 Testvector.CopyVector(&Binder->GetOtherAtom(Walker)->x); 912 Testvector.InverseMatrixMultiplication(matrix); 913 Testvector.AddVector(&Translationvector); 914 Testvector.MatrixMultiplication(matrix); 915 center.AddVector(&Testvector); 916 cout << Verbose(1) << "Hydrogen vector is: "; 917 Testvector.Output((ofstream *)&cout); 918 cout << endl; 919 } 920 } 921 } 922 922 #endif 923 924 925 926 923 } 924 } while (!flag); 925 Free((void **)&matrix, "molecule::DetermineCenter: *matrix"); 926 center.Scale(1./(double)AtomCount); 927 927 }; 928 928 … … 933 933 void molecule::PrincipalAxisSystem(ofstream *out, bool DoRotate) 934 934 { 935 atom *ptr = start;// start at first in list936 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 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 935 atom *ptr = start; // start at first in list 936 double InertiaTensor[NDIM*NDIM]; 937 Vector *CenterOfGravity = DetermineCenterOfGravity(out); 938 939 CenterAtVector(out, CenterOfGravity); 940 941 // reset inertia tensor 942 for(int i=0;i<NDIM*NDIM;i++) 943 InertiaTensor[i] = 0.; 944 945 // sum up inertia tensor 946 while (ptr->next != end) { 947 ptr = ptr->next; 948 Vector x; 949 x.CopyVector(&ptr->x); 950 //x.SubtractVector(CenterOfGravity); 951 InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]); 952 InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]); 953 InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]); 954 InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]); 955 InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]); 956 InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]); 957 InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]); 958 InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]); 959 InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]); 960 } 961 // print InertiaTensor for debugging 962 *out << "The inertia tensor is:" << endl; 963 for(int i=0;i<NDIM;i++) { 964 for(int j=0;j<NDIM;j++) 965 *out << InertiaTensor[i*NDIM+j] << " "; 966 *out << endl; 967 } 968 *out << endl; 969 970 // diagonalize to determine principal axis system 971 gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(NDIM); 972 gsl_matrix_view m = gsl_matrix_view_array(InertiaTensor, NDIM, NDIM); 973 gsl_vector *eval = gsl_vector_alloc(NDIM); 974 gsl_matrix *evec = gsl_matrix_alloc(NDIM, NDIM); 975 gsl_eigen_symmv(&m.matrix, eval, evec, T); 976 gsl_eigen_symmv_free(T); 977 gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC); 978 979 for(int i=0;i<NDIM;i++) { 980 *out << Verbose(1) << "eigenvalue = " << gsl_vector_get(eval, i); 981 *out << ", eigenvector = (" << evec->data[i * evec->tda + 0] << "," << evec->data[i * evec->tda + 1] << "," << evec->data[i * evec->tda + 2] << ")" << endl; 982 } 983 984 // check whether we rotate or not 985 if (DoRotate) { 986 *out << Verbose(1) << "Transforming molecule into PAS ... "; 987 // the eigenvectors specify the transformation matrix 988 ptr = start; 989 while (ptr->next != end) { 990 ptr = ptr->next; 991 for (int j=0;j<MDSteps;j++) 992 Trajectories[ptr].R.at(j).MatrixMultiplication(evec->data); 993 ptr->x.MatrixMultiplication(evec->data); 994 } 995 *out << "done." << endl; 996 997 // summing anew for debugging (resulting matrix has to be diagonal!) 998 // reset inertia tensor 999 for(int i=0;i<NDIM*NDIM;i++) 1000 InertiaTensor[i] = 0.; 1001 1002 // sum up inertia tensor 1003 ptr = start; 1004 while (ptr->next != end) { 1005 ptr = ptr->next; 1006 Vector x; 1007 x.CopyVector(&ptr->x); 1008 //x.SubtractVector(CenterOfGravity); 1009 InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]); 1010 InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]); 1011 InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]); 1012 InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]); 1013 InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]); 1014 InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]); 1015 InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]); 1016 InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]); 1017 InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]); 1018 } 1019 // print InertiaTensor for debugging 1020 *out << "The inertia tensor is:" << endl; 1021 for(int i=0;i<NDIM;i++) { 1022 for(int j=0;j<NDIM;j++) 1023 *out << InertiaTensor[i*NDIM+j] << " "; 1024 *out << endl; 1025 } 1026 *out << endl; 1027 } 1028 1029 // free everything 1030 delete(CenterOfGravity); 1031 gsl_vector_free(eval); 1032 gsl_matrix_free(evec); 1033 1033 }; 1034 1034 … … 1044 1044 bool molecule::VerletForceIntegration(char *file, double delta_t, bool IsAngstroem) 1045 1045 { 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 CountElements();// make sure ElementsInMolecule is up to date1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 // 1073 // 1074 // 1075 // 1076 // 1077 // 1078 // 1079 // 1080 // 1081 // 1082 1083 1084 1085 1086 1087 a = delta_t*0.5/IonMass;// (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 Trajectories[walker].R.at(MDSteps).x[d] += 0.5*delta_t*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d])/IonMass;// F = m * a and s = 0.5 * F/m * t^2 = F * a * t1107 1108 1109 1110 1111 1112 1113 // 1114 // 1115 // cout << Trajectories[walker].R.at(MDSteps).x[d] << " ";// next step1116 // 1117 // 1118 // cout << Trajectories[walker].U.at(MDSteps).x[d] << " ";// next step1119 // 1120 1121 1122 1123 1124 1125 1126 1127 // 1128 // 1129 // 1130 // 1131 // 1132 // 1133 // IonMass += walker->type->mass;// sum up total mass1134 // 1135 // 1136 // 1137 // 1138 // 1139 // 1140 // 1141 // 1142 // 1143 // 1144 // 1145 1146 1147 1148 1149 1046 element *runner = elemente->start; 1047 atom *walker = NULL; 1048 int AtomNo; 1049 ifstream input(file); 1050 string token; 1051 stringstream item; 1052 double a, IonMass; 1053 ForceMatrix Force; 1054 Vector tmpvector; 1055 1056 CountElements(); // make sure ElementsInMolecule is up to date 1057 1058 // check file 1059 if (input == NULL) { 1060 return false; 1061 } else { 1062 // parse file into ForceMatrix 1063 if (!Force.ParseMatrix(file, 0,0,0)) { 1064 cerr << "Could not parse Force Matrix file " << file << "." << endl; 1065 return false; 1066 } 1067 if (Force.RowCounter[0] != AtomCount) { 1068 cerr << "Mismatch between number of atoms in file " << Force.RowCounter[0] << " and in molecule " << AtomCount << "." << endl; 1069 return false; 1070 } 1071 // correct Forces 1072 // for(int d=0;d<NDIM;d++) 1073 // tmpvector.x[d] = 0.; 1074 // for(int i=0;i<AtomCount;i++) 1075 // for(int d=0;d<NDIM;d++) { 1076 // tmpvector.x[d] += Force.Matrix[0][i][d+5]; 1077 // } 1078 // for(int i=0;i<AtomCount;i++) 1079 // for(int d=0;d<NDIM;d++) { 1080 // Force.Matrix[0][i][d+5] -= tmpvector.x[d]/(double)AtomCount; 1081 // } 1082 // and perform Verlet integration for each atom with position, velocity and force vector 1083 runner = elemente->start; 1084 while (runner->next != elemente->end) { // go through every element 1085 runner = runner->next; 1086 IonMass = runner->mass; 1087 a = delta_t*0.5/IonMass; // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a 1088 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1089 AtomNo = 0; 1090 walker = start; 1091 while (walker->next != end) { // go through every atom of this element 1092 walker = walker->next; 1093 if (walker->type == runner) { // if this atom fits to element 1094 // check size of vectors 1095 if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) { 1096 //cout << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl; 1097 Trajectories[walker].R.resize(MDSteps+10); 1098 Trajectories[walker].U.resize(MDSteps+10); 1099 Trajectories[walker].F.resize(MDSteps+10); 1100 } 1101 // 1. calculate x(t+\delta t) 1102 for (int d=0; d<NDIM; d++) { 1103 Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5]; 1104 Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d]; 1105 Trajectories[walker].R.at(MDSteps).x[d] += delta_t*(Trajectories[walker].U.at(MDSteps-1).x[d]); 1106 Trajectories[walker].R.at(MDSteps).x[d] += 0.5*delta_t*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d])/IonMass; // F = m * a and s = 0.5 * F/m * t^2 = F * a * t 1107 } 1108 // 2. Calculate v(t+\delta t) 1109 for (int d=0; d<NDIM; d++) { 1110 Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d]; 1111 Trajectories[walker].U.at(MDSteps).x[d] += 0.5*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d]+Trajectories[walker].F.at(MDSteps).x[d])/IonMass; 1112 } 1113 // cout << "Integrated position&velocity of step " << (MDSteps) << ": ("; 1114 // for (int d=0;d<NDIM;d++) 1115 // cout << Trajectories[walker].R.at(MDSteps).x[d] << " "; // next step 1116 // cout << ")\t("; 1117 // for (int d=0;d<NDIM;d++) 1118 // cout << Trajectories[walker].U.at(MDSteps).x[d] << " "; // next step 1119 // cout << ")" << endl; 1120 // next atom 1121 AtomNo++; 1122 } 1123 } 1124 } 1125 } 1126 } 1127 // // correct velocities (rather momenta) so that center of mass remains motionless 1128 // tmpvector.zero() 1129 // IonMass = 0.; 1130 // walker = start; 1131 // while (walker->next != end) { // go through every atom 1132 // walker = walker->next; 1133 // IonMass += walker->type->mass; // sum up total mass 1134 // for(int d=0;d<NDIM;d++) { 1135 // tmpvector.x[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass; 1136 // } 1137 // } 1138 // walker = start; 1139 // while (walker->next != end) { // go through every atom of this element 1140 // walker = walker->next; 1141 // for(int d=0;d<NDIM;d++) { 1142 // Trajectories[walker].U.at(MDSteps).x[d] -= tmpvector.x[d]*walker->type->mass/IonMass; 1143 // } 1144 // } 1145 MDSteps++; 1146 1147 1148 // exit 1149 return true; 1150 1150 }; 1151 1151 … … 1155 1155 void molecule::Align(Vector *n) 1156 1156 { 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 ptr->x.x[0] =cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];1172 1173 1174 1175 Trajectories[ptr].R.at(j).x[0] =cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];1176 1177 1178 1179 1180 1181 n->x[0] = cos(alpha) * tmp +sin(alpha) * n->x[2];1182 n->x[2] = -sin(alpha) * tmp +cos(alpha) * n->x[2];1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 ptr->x.x[1] =cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];1195 1196 1197 1198 Trajectories[ptr].R.at(j).x[1] =cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];1199 1200 1201 1202 1203 1204 n->x[1] = cos(alpha) * tmp +sin(alpha) * n->x[2];1205 n->x[2] = -sin(alpha) * tmp +cos(alpha) * n->x[2];1206 1207 1208 1209 1210 1157 atom *ptr = start; 1158 double alpha, tmp; 1159 Vector z_axis; 1160 z_axis.x[0] = 0.; 1161 z_axis.x[1] = 0.; 1162 z_axis.x[2] = 1.; 1163 1164 // rotate on z-x plane 1165 cout << Verbose(0) << "Begin of Aligning all atoms." << endl; 1166 alpha = atan(-n->x[0]/n->x[2]); 1167 cout << Verbose(1) << "Z-X-angle: " << alpha << " ... "; 1168 while (ptr->next != end) { 1169 ptr = ptr->next; 1170 tmp = ptr->x.x[0]; 1171 ptr->x.x[0] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1172 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1173 for (int j=0;j<MDSteps;j++) { 1174 tmp = Trajectories[ptr].R.at(j).x[0]; 1175 Trajectories[ptr].R.at(j).x[0] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1176 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1177 } 1178 } 1179 // rotate n vector 1180 tmp = n->x[0]; 1181 n->x[0] = cos(alpha) * tmp + sin(alpha) * n->x[2]; 1182 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2]; 1183 cout << Verbose(1) << "alignment vector after first rotation: "; 1184 n->Output((ofstream *)&cout); 1185 cout << endl; 1186 1187 // rotate on z-y plane 1188 ptr = start; 1189 alpha = atan(-n->x[1]/n->x[2]); 1190 cout << Verbose(1) << "Z-Y-angle: " << alpha << " ... "; 1191 while (ptr->next != end) { 1192 ptr = ptr->next; 1193 tmp = ptr->x.x[1]; 1194 ptr->x.x[1] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1195 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1196 for (int j=0;j<MDSteps;j++) { 1197 tmp = Trajectories[ptr].R.at(j).x[1]; 1198 Trajectories[ptr].R.at(j).x[1] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1199 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1200 } 1201 } 1202 // rotate n vector (for consistency check) 1203 tmp = n->x[1]; 1204 n->x[1] = cos(alpha) * tmp + sin(alpha) * n->x[2]; 1205 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2]; 1206 1207 cout << Verbose(1) << "alignment vector after second rotation: "; 1208 n->Output((ofstream *)&cout); 1209 cout << Verbose(1) << endl; 1210 cout << Verbose(0) << "End of Aligning all atoms." << endl; 1211 1211 }; 1212 1212 … … 1217 1217 bool molecule::RemoveAtom(atom *pointer) 1218 1218 { 1219 if (ElementsInMolecule[pointer->type->Z] != 0)// this would indicate an error1220 ElementsInMolecule[pointer->type->Z]--;// decrease number of atom of this element1221 1222 1223 if (ElementsInMolecule[pointer->type->Z] == 0)// was last atom of this element?1224 1225 1226 1219 if (ElementsInMolecule[pointer->type->Z] != 0) // this would indicate an error 1220 ElementsInMolecule[pointer->type->Z]--; // decrease number of atom of this element 1221 else 1222 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl; 1223 if (ElementsInMolecule[pointer->type->Z] == 0) // was last atom of this element? 1224 ElementCount--; 1225 Trajectories.erase(pointer); 1226 return remove(pointer, start, end); 1227 1227 }; 1228 1228 … … 1251 1251 bool molecule::CleanupMolecule() 1252 1252 { 1253 1253 return (cleanup(start,end) && cleanup(first,last)); 1254 1254 }; 1255 1255 … … 1258 1258 * \return pointer to atom or NULL 1259 1259 */ 1260 atom * molecule::FindAtom(int Nr) 1261 1262 1263 1264 1265 1266 1267 1268 1260 atom * molecule::FindAtom(int Nr) const{ 1261 atom * walker = find(&Nr, start,end); 1262 if (walker != NULL) { 1263 //cout << Verbose(0) << "Found Atom Nr. " << walker->nr << endl; 1264 return walker; 1265 } else { 1266 cout << Verbose(0) << "Atom not found in list." << endl; 1267 return NULL; 1268 } 1269 1269 }; 1270 1270 … … 1274 1274 atom * molecule::AskAtom(string text) 1275 1275 { 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1276 int No; 1277 atom *ion = NULL; 1278 do { 1279 //cout << Verbose(0) << "============Atom list==========================" << endl; 1280 //mol->Output((ofstream *)&cout); 1281 //cout << Verbose(0) << "===============================================" << endl; 1282 cout << Verbose(0) << text; 1283 cin >> No; 1284 ion = this->FindAtom(No); 1285 } while (ion == NULL); 1286 return ion; 1287 1287 }; 1288 1288 … … 1293 1293 bool molecule::CheckBounds(const Vector *x) const 1294 1294 { 1295 1296 1297 1298 1299 1300 1301 1302 1295 bool result = true; 1296 int j =-1; 1297 for (int i=0;i<NDIM;i++) { 1298 j += i+1; 1299 result = result && ((x->x[i] >= 0) && (x->x[i] < cell_size[j])); 1300 } 1301 //return result; 1302 return true; /// probably not gonna use the check no more 1303 1303 }; 1304 1304 … … 1310 1310 double LeastSquareDistance (const gsl_vector * x, void * params) 1311 1311 { 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 c.CopyVector(&ptr->x);// copy vector to temporary one1329 c.SubtractVector(&a);// subtract offset vector1330 t = c.ScalarProduct(&b);// get direction parameter1331 d.CopyVector(&b);// and create vector1332 1333 c.SubtractVector(&d);// ... yielding distance vector1334 res += d.ScalarProduct((const Vector *)&d);// add squared distance1335 1336 1337 1312 double res = 0, t; 1313 Vector a,b,c,d; 1314 struct lsq_params *par = (struct lsq_params *)params; 1315 atom *ptr = par->mol->start; 1316 1317 // initialize vectors 1318 a.x[0] = gsl_vector_get(x,0); 1319 a.x[1] = gsl_vector_get(x,1); 1320 a.x[2] = gsl_vector_get(x,2); 1321 b.x[0] = gsl_vector_get(x,3); 1322 b.x[1] = gsl_vector_get(x,4); 1323 b.x[2] = gsl_vector_get(x,5); 1324 // go through all atoms 1325 while (ptr != par->mol->end) { 1326 ptr = ptr->next; 1327 if (ptr->type == ((struct lsq_params *)params)->type) { // for specific type 1328 c.CopyVector(&ptr->x); // copy vector to temporary one 1329 c.SubtractVector(&a); // subtract offset vector 1330 t = c.ScalarProduct(&b); // get direction parameter 1331 d.CopyVector(&b); // and create vector 1332 d.Scale(&t); 1333 c.SubtractVector(&d); // ... yielding distance vector 1334 res += d.ScalarProduct((const Vector *)&d); // add squared distance 1335 } 1336 } 1337 return res; 1338 1338 }; 1339 1339 … … 1343 1343 void molecule::GetAlignvector(struct lsq_params * par) const 1344 1344 { 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 gsl_vector_set (par->x, 0, 0.0);// offset1368 1369 1370 gsl_vector_set (par->x, 3, 0.0);// direction1371 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 1345 int np = 6; 1346 1347 const gsl_multimin_fminimizer_type *T = 1348 gsl_multimin_fminimizer_nmsimplex; 1349 gsl_multimin_fminimizer *s = NULL; 1350 gsl_vector *ss; 1351 gsl_multimin_function minex_func; 1352 1353 size_t iter = 0, i; 1354 int status; 1355 double size; 1356 1357 /* Initial vertex size vector */ 1358 ss = gsl_vector_alloc (np); 1359 1360 /* Set all step sizes to 1 */ 1361 gsl_vector_set_all (ss, 1.0); 1362 1363 /* Starting point */ 1364 par->x = gsl_vector_alloc (np); 1365 par->mol = this; 1366 1367 gsl_vector_set (par->x, 0, 0.0); // offset 1368 gsl_vector_set (par->x, 1, 0.0); 1369 gsl_vector_set (par->x, 2, 0.0); 1370 gsl_vector_set (par->x, 3, 0.0); // direction 1371 gsl_vector_set (par->x, 4, 0.0); 1372 gsl_vector_set (par->x, 5, 1.0); 1373 1374 /* Initialize method and iterate */ 1375 minex_func.f = &LeastSquareDistance; 1376 minex_func.n = np; 1377 minex_func.params = (void *)par; 1378 1379 s = gsl_multimin_fminimizer_alloc (T, np); 1380 gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss); 1381 1382 do 1383 { 1384 iter++; 1385 status = gsl_multimin_fminimizer_iterate(s); 1386 1387 if (status) 1388 break; 1389 1390 size = gsl_multimin_fminimizer_size (s); 1391 status = gsl_multimin_test_size (size, 1e-2); 1392 1393 if (status == GSL_SUCCESS) 1394 { 1395 printf ("converged to minimum at\n"); 1396 } 1397 1398 printf ("%5d ", (int)iter); 1399 for (i = 0; i < (size_t)np; i++) 1400 { 1401 printf ("%10.3e ", gsl_vector_get (s->x, i)); 1402 } 1403 printf ("f() = %7.3f size = %.3f\n", s->fval, size); 1404 } 1405 while (status == GSL_CONTINUE && iter < 100); 1406 1407 for (i=0;i<(size_t)np;i++) 1408 gsl_vector_set(par->x, i, gsl_vector_get(s->x, i)); 1409 //gsl_vector_free(par->x); 1410 gsl_vector_free(ss); 1411 gsl_multimin_fminimizer_free (s); 1412 1412 }; 1413 1413 … … 1417 1417 bool molecule::Output(ofstream *out) 1418 1418 { 1419 1420 1421 1422 1423 1424 1425 1426 1427 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2]MoveType (0 MoveIon, 1 FixedIon)" << endl;1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1419 element *runner; 1420 atom *walker = NULL; 1421 int ElementNo, AtomNo; 1422 CountElements(); 1423 1424 if (out == NULL) { 1425 return false; 1426 } else { 1427 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2] MoveType (0 MoveIon, 1 FixedIon)" << endl; 1428 ElementNo = 0; 1429 runner = elemente->start; 1430 while (runner->next != elemente->end) { // go through every element 1431 runner = runner->next; 1432 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1433 ElementNo++; 1434 AtomNo = 0; 1435 walker = start; 1436 while (walker->next != end) { // go through every atom of this element 1437 walker = walker->next; 1438 if (walker->type == runner) { // if this atom fits to element 1439 AtomNo++; 1440 walker->Output(ElementNo, AtomNo, out); // removed due to trajectories 1441 } 1442 } 1443 } 1444 } 1445 return true; 1446 } 1447 1447 }; 1448 1448 … … 1452 1452 bool molecule::OutputTrajectories(ofstream *out) 1453 1453 { 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2]MoveType (0 MoveIon, 1 FixedIon)" << endl;1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t"<< fixed << setprecision(9) << showpoint;1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1454 element *runner = NULL; 1455 atom *walker = NULL; 1456 int ElementNo, AtomNo; 1457 CountElements(); 1458 1459 if (out == NULL) { 1460 return false; 1461 } else { 1462 for (int step = 0; step < MDSteps; step++) { 1463 if (step == 0) { 1464 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2] MoveType (0 MoveIon, 1 FixedIon)" << endl; 1465 } else { 1466 *out << "# ====== MD step " << step << " =========" << endl; 1467 } 1468 ElementNo = 0; 1469 runner = elemente->start; 1470 while (runner->next != elemente->end) { // go through every element 1471 runner = runner->next; 1472 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1473 ElementNo++; 1474 AtomNo = 0; 1475 walker = start; 1476 while (walker->next != end) { // go through every atom of this element 1477 walker = walker->next; 1478 if (walker->type == runner) { // if this atom fits to element 1479 AtomNo++; 1480 *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t" << fixed << setprecision(9) << showpoint; 1481 *out << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2]; 1482 *out << "\t" << walker->FixedIon; 1483 if (Trajectories[walker].U.at(step).Norm() > MYEPSILON) 1484 *out << "\t" << scientific << setprecision(6) << Trajectories[walker].U.at(step).x[0] << "\t" << Trajectories[walker].U.at(step).x[1] << "\t" << Trajectories[walker].U.at(step).x[2] << "\t"; 1485 if (Trajectories[walker].F.at(step).Norm() > MYEPSILON) 1486 *out << "\t" << scientific << setprecision(6) << Trajectories[walker].F.at(step).x[0] << "\t" << Trajectories[walker].F.at(step).x[1] << "\t" << Trajectories[walker].F.at(step).x[2] << "\t"; 1487 *out << "\t# Number in molecule " << walker->nr << endl; 1488 } 1489 } 1490 } 1491 } 1492 } 1493 return true; 1494 } 1495 1495 }; 1496 1496 … … 1500 1500 void molecule::OutputListOfBonds(ofstream *out) const 1501 1501 { 1502 1503 1504 1505 1502 *out << Verbose(2) << endl << "From Contents of ListOfBondsPerAtom, all non-hydrogen atoms:" << endl; 1503 atom *Walker = start; 1504 while (Walker->next != end) { 1505 Walker = Walker->next; 1506 1506 #ifdef ADDHYDROGEN 1507 if (Walker->type->Z != 1) {// regard only non-hydrogen1507 if (Walker->type->Z != 1) { // regard only non-hydrogen 1508 1508 #endif 1509 1510 1511 1512 1509 *out << Verbose(2) << "Atom " << Walker->Name << " has Bonds: "<<endl; 1510 for(int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) { 1511 *out << Verbose(3) << *(ListOfBondsPerAtom)[Walker->nr][j] << endl; 1512 } 1513 1513 #ifdef ADDHYDROGEN 1514 1514 } 1515 1515 #endif 1516 1517 1516 } 1517 *out << endl; 1518 1518 }; 1519 1519 … … 1521 1521 * \param *out stream pointer 1522 1522 */ 1523 bool molecule::Checkout(ofstream *out) 1524 { 1525 1523 bool molecule::Checkout(ofstream *out) const 1524 { 1525 return elemente->Checkout(out, ElementsInMolecule); 1526 1526 }; 1527 1527 … … 1531 1531 bool molecule::OutputTrajectoriesXYZ(ofstream *out) 1532 1532 { 1533 1534 1535 1536 1537 now = time((time_t *)NULL);// Get the system time and put it into 'now' as 'calender time'1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1533 atom *walker = NULL; 1534 int No = 0; 1535 time_t now; 1536 1537 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 1538 walker = start; 1539 while (walker->next != end) { // go through every atom and count 1540 walker = walker->next; 1541 No++; 1542 } 1543 if (out != NULL) { 1544 for (int step=0;step<MDSteps;step++) { 1545 *out << No << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now); 1546 walker = start; 1547 while (walker->next != end) { // go through every atom of this element 1548 walker = walker->next; 1549 *out << walker->type->symbol << "\t" << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2] << endl; 1550 } 1551 } 1552 return true; 1553 } else 1554 return false; 1555 1555 }; 1556 1556 … … 1560 1560 bool molecule::OutputXYZ(ofstream *out) const 1561 1561 { 1562 1563 1564 1565 1566 1567 now = time((time_t *)NULL);// Get the system time and put it into 'now' as 'calender time'1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1562 atom *walker = NULL; 1563 int AtomNo = 0, ElementNo; 1564 time_t now; 1565 element *runner = NULL; 1566 1567 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 1568 walker = start; 1569 while (walker->next != end) { // go through every atom and count 1570 walker = walker->next; 1571 AtomNo++; 1572 } 1573 if (out != NULL) { 1574 *out << AtomNo << "\n\tCreated by molecuilder on " << ctime(&now); 1575 ElementNo = 0; 1576 runner = elemente->start; 1577 while (runner->next != elemente->end) { // go through every element 1578 runner = runner->next; 1579 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1580 ElementNo++; 1581 walker = start; 1582 while (walker->next != end) { // go through every atom of this element 1583 walker = walker->next; 1584 if (walker->type == runner) { // if this atom fits to element 1585 walker->OutputXYZLine(out); 1586 } 1587 } 1588 } 1589 } 1590 return true; 1591 } else 1592 return false; 1593 1593 }; 1594 1594 … … 1598 1598 void molecule::CountAtoms(ofstream *out) 1599 1599 { 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 Walker->nr = i;// update number in molecule (for easier referencing in FragmentMolecule lateron)1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1600 int i = 0; 1601 atom *Walker = start; 1602 while (Walker->next != end) { 1603 Walker = Walker->next; 1604 i++; 1605 } 1606 if ((AtomCount == 0) || (i != AtomCount)) { 1607 *out << Verbose(3) << "Mismatch in AtomCount " << AtomCount << " and recounted number " << i << ", renaming all." << endl; 1608 AtomCount = i; 1609 1610 // count NonHydrogen atoms and give each atom a unique name 1611 if (AtomCount != 0) { 1612 i=0; 1613 NoNonHydrogen = 0; 1614 Walker = start; 1615 while (Walker->next != end) { 1616 Walker = Walker->next; 1617 Walker->nr = i; // update number in molecule (for easier referencing in FragmentMolecule lateron) 1618 if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it 1619 NoNonHydrogen++; 1620 Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name"); 1621 Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name"); 1622 sprintf(Walker->Name, "%2s%02d", Walker->type->symbol, Walker->nr+1); 1623 *out << "Naming atom nr. " << Walker->nr << " " << Walker->Name << "." << endl; 1624 i++; 1625 } 1626 } else 1627 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 1628 } 1629 1629 }; 1630 1630 … … 1633 1633 void molecule::CountElements() 1634 1634 { 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1635 int i = 0; 1636 for(i=MAX_ELEMENTS;i--;) 1637 ElementsInMolecule[i] = 0; 1638 ElementCount = 0; 1639 1640 atom *walker = start; 1641 while (walker->next != end) { 1642 walker = walker->next; 1643 ElementsInMolecule[walker->type->Z]++; 1644 i++; 1645 } 1646 for(i=MAX_ELEMENTS;i--;) 1647 ElementCount += (ElementsInMolecule[i] != 0 ? 1 : 0); 1648 1648 }; 1649 1649 … … 1655 1655 int molecule::CountCyclicBonds(ofstream *out) 1656 1656 { 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1657 int No = 0; 1658 int *MinimumRingSize = NULL; 1659 MoleculeLeafClass *Subgraphs = NULL; 1660 class StackClass<bond *> *BackEdgeStack = NULL; 1661 bond *Binder = first; 1662 if ((Binder->next != last) && (Binder->next->Type == Undetermined)) { 1663 *out << Verbose(0) << "No Depth-First-Search analysis performed so far, calling ..." << endl; 1664 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack); 1665 while (Subgraphs->next != NULL) { 1666 Subgraphs = Subgraphs->next; 1667 delete(Subgraphs->previous); 1668 } 1669 delete(Subgraphs); 1670 delete[](MinimumRingSize); 1671 } 1672 while(Binder->next != last) { 1673 Binder = Binder->next; 1674 if (Binder->Cyclic) 1675 No++; 1676 } 1677 delete(BackEdgeStack); 1678 return No; 1679 1679 }; 1680 1680 /** Returns Shading as a char string. … … 1684 1684 string molecule::GetColor(enum Shading color) 1685 1685 { 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1686 switch(color) { 1687 case white: 1688 return "white"; 1689 break; 1690 case lightgray: 1691 return "lightgray"; 1692 break; 1693 case darkgray: 1694 return "darkgray"; 1695 break; 1696 case black: 1697 return "black"; 1698 break; 1699 default: 1700 return "uncolored"; 1701 break; 1702 }; 1703 1703 }; 1704 1704 … … 1709 1709 void molecule::CalculateOrbitals(class config &configuration) 1710 1710 { 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1711 configuration.MaxPsiDouble = configuration.PsiMaxNoDown = configuration.PsiMaxNoUp = configuration.PsiType = 0; 1712 for(int i=MAX_ELEMENTS;i--;) { 1713 if (ElementsInMolecule[i] != 0) { 1714 //cout << "CalculateOrbitals: " << elemente->FindElement(i)->name << " has a valence of " << (int)elemente->FindElement(i)->Valence << " and there are " << ElementsInMolecule[i] << " of it." << endl; 1715 configuration.MaxPsiDouble += ElementsInMolecule[i]*((int)elemente->FindElement(i)->Valence); 1716 } 1717 } 1718 configuration.PsiMaxNoDown = configuration.MaxPsiDouble/2 + (configuration.MaxPsiDouble % 2); 1719 configuration.PsiMaxNoUp = configuration.MaxPsiDouble/2; 1720 configuration.MaxPsiDouble /= 2; 1721 configuration.PsiType = (configuration.PsiMaxNoDown == configuration.PsiMaxNoUp) ? 0 : 1; 1722 if ((configuration.PsiType == 1) && (configuration.ProcPEPsi < 2)) { 1723 configuration.ProcPEGamma /= 2; 1724 configuration.ProcPEPsi *= 2; 1725 } else { 1726 configuration.ProcPEGamma *= configuration.ProcPEPsi; 1727 configuration.ProcPEPsi = 1; 1728 } 1729 configuration.InitMaxMinStopStep = configuration.MaxMinStopStep = configuration.MaxPsiDouble; 1730 1730 }; 1731 1731 … … 1736 1736 { 1737 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1738 // 1 We will parse bonds out of the dbond file created by tremolo. 1739 int atom1, atom2, temp; 1740 atom *Walker, *OtherWalker; 1741 1742 if (!input) 1743 { 1744 cout << Verbose(1) << "Opening silica failed \n"; 1745 }; 1746 1747 *input >> ws >> atom1; 1748 *input >> ws >> atom2; 1749 cout << Verbose(1) << "Scanning file\n"; 1750 while (!input->eof()) // Check whether we read everything already 1751 { 1752 *input >> ws >> atom1; 1753 *input >> ws >> atom2; 1754 if(atom2<atom1) //Sort indices of atoms in order 1755 { 1756 temp=atom1; 1757 atom1=atom2; 1758 atom2=temp; 1759 }; 1760 1761 Walker=start; 1762 while(Walker-> nr != atom1) // Find atom corresponding to first index 1763 { 1764 Walker = Walker->next; 1765 }; 1766 OtherWalker = Walker->next; 1767 while(OtherWalker->nr != atom2) // Find atom corresponding to second index 1768 { 1769 OtherWalker= OtherWalker->next; 1770 }; 1771 AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices. 1772 1773 } 1774 1775 CreateListOfBondsPerAtom(out); 1776 1776 1777 1777 }; … … 1784 1784 * To make it O(N log N) the function uses the linked-cell technique as follows: 1785 1785 * The procedure is step-wise: 1786 * 1787 * 1788 * 1789 * 1790 * 1791 * 1792 * 1793 * 1786 * -# Remove every bond in list 1787 * -# Count the atoms in the molecule with CountAtoms() 1788 * -# partition cell into smaller linked cells of size \a bonddistance 1789 * -# put each atom into its corresponding cell 1790 * -# go through every cell, check the atoms therein against all possible bond partners in the 27 adjacent cells, add bond if true 1791 * -# create the list of bonds via CreateListOfBondsPerAtom() 1792 * -# correct the bond degree iteratively (single->double->triple bond) 1793 * -# finally print the bond list to \a *out if desired 1794 1794 * \param *out out stream for printing the matrix, NULL if no output 1795 1795 * \param bonddistance length of linked cells (i.e. maximum minimal length checked) … … 1799 1799 { 1800 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 if ((first->next != last) && (last->previous != first)) {// there are bonds present1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 //*out << Verbose(1) << "divisor[" << i << "]= " << divisor[i] << "." << endl;1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 if (CellList[index] == NULL)// allocate molecule if not done1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 while (Walker->next != CellList[Index]->end) {// go through every atom1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 if (CellList[index] != NULL) {// if there are any atoms in this cell1883 1884 while(OtherWalker->next != CellList[index]->end) {// go through every atom in this cell1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 AddBond(Walker->father, OtherWalker->father, 1);// also increases molecule::BondCount1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1801 atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL; 1802 int No, NoBonds, CandidateBondNo; 1803 int NumberCells, divisor[NDIM], n[NDIM], N[NDIM], index, Index, j; 1804 molecule **CellList; 1805 double distance, MinDistance, MaxDistance; 1806 double *matrix = ReturnFullMatrixforSymmetric(cell_size); 1807 Vector x; 1808 int FalseBondDegree = 0; 1809 1810 BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem); 1811 *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl; 1812 // remove every bond from the list 1813 if ((first->next != last) && (last->previous != first)) { // there are bonds present 1814 cleanup(first,last); 1815 } 1816 1817 // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering) 1818 CountAtoms(out); 1819 *out << Verbose(1) << "AtomCount " << AtomCount << "." << endl; 1820 1821 if (AtomCount != 0) { 1822 // 1. find divisor for each axis, such that a sphere with radius of at least bonddistance can be placed into each cell 1823 j=-1; 1824 for (int i=0;i<NDIM;i++) { 1825 j += i+1; 1826 divisor[i] = (int)floor(cell_size[j]/bonddistance); // take smaller value such that size of linked cell is at least bonddistance 1827 //*out << Verbose(1) << "divisor[" << i << "] = " << divisor[i] << "." << endl; 1828 } 1829 // 2a. allocate memory for the cell list 1830 NumberCells = divisor[0]*divisor[1]*divisor[2]; 1831 *out << Verbose(1) << "Allocating " << NumberCells << " cells." << endl; 1832 CellList = (molecule **) Malloc(sizeof(molecule *)*NumberCells, "molecule::CreateAdjacencyList - ** CellList"); 1833 for (int i=NumberCells;i--;) 1834 CellList[i] = NULL; 1835 1836 // 2b. put all atoms into its corresponding list 1837 Walker = start; 1838 while(Walker->next != end) { 1839 Walker = Walker->next; 1840 //*out << Verbose(1) << "Current atom is " << *Walker << " with coordinates "; 1841 //Walker->x.Output(out); 1842 //*out << "." << endl; 1843 // compute the cell by the atom's coordinates 1844 j=-1; 1845 for (int i=0;i<NDIM;i++) { 1846 j += i+1; 1847 x.CopyVector(&(Walker->x)); 1848 x.KeepPeriodic(out, matrix); 1849 n[i] = (int)floor(x.x[i]/cell_size[j]*(double)divisor[i]); 1850 } 1851 index = n[2] + (n[1] + n[0] * divisor[1]) * divisor[2]; 1852 //*out << Verbose(1) << "Atom " << *Walker << " goes into cell number [" << n[0] << "," << n[1] << "," << n[2] << "] = " << index << "." << endl; 1853 // add copy atom to this cell 1854 if (CellList[index] == NULL) // allocate molecule if not done 1855 CellList[index] = new molecule(elemente); 1856 OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference 1857 //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl; 1858 } 1859 //for (int i=0;i<NumberCells;i++) 1860 //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl; 1861 1862 1863 // 3a. go through every cell 1864 for (N[0]=divisor[0];N[0]--;) 1865 for (N[1]=divisor[1];N[1]--;) 1866 for (N[2]=divisor[2];N[2]--;) { 1867 Index = N[2] + (N[1] + N[0] * divisor[1]) * divisor[2]; 1868 if (CellList[Index] != NULL) { // if there atoms in this cell 1869 //*out << Verbose(1) << "Current cell is " << Index << "." << endl; 1870 // 3b. for every atom therein 1871 Walker = CellList[Index]->start; 1872 while (Walker->next != CellList[Index]->end) { // go through every atom 1873 Walker = Walker->next; 1874 //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl; 1875 // 3c. check for possible bond between each atom in this and every one in the 27 cells 1876 for (n[0]=-1;n[0]<=1;n[0]++) 1877 for (n[1]=-1;n[1]<=1;n[1]++) 1878 for (n[2]=-1;n[2]<=1;n[2]++) { 1879 // compute the index of this comparison cell and make it periodic 1880 index = ((N[2]+n[2]+divisor[2])%divisor[2]) + (((N[1]+n[1]+divisor[1])%divisor[1]) + ((N[0]+n[0]+divisor[0])%divisor[0]) * divisor[1]) * divisor[2]; 1881 //*out << Verbose(1) << "Number of comparison cell is " << index << "." << endl; 1882 if (CellList[index] != NULL) { // if there are any atoms in this cell 1883 OtherWalker = CellList[index]->start; 1884 while(OtherWalker->next != CellList[index]->end) { // go through every atom in this cell 1885 OtherWalker = OtherWalker->next; 1886 //*out << Verbose(0) << "Current comparison atom is " << *OtherWalker << "." << endl; 1887 /// \todo periodic check is missing here! 1888 //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl; 1889 MinDistance = OtherWalker->type->CovalentRadius + Walker->type->CovalentRadius; 1890 MinDistance *= (IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem; 1891 MaxDistance = MinDistance + BONDTHRESHOLD; 1892 MinDistance -= BONDTHRESHOLD; 1893 distance = OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size); 1894 if ((OtherWalker->father->nr > Walker->father->nr) && (distance <= MaxDistance*MaxDistance) && (distance >= MinDistance*MinDistance)) { // create bond if distance is smaller 1895 //*out << Verbose(1) << "Adding Bond between " << *Walker << " and " << *OtherWalker << " in distance " << sqrt(distance) << "." << endl; 1896 AddBond(Walker->father, OtherWalker->father, 1); // also increases molecule::BondCount 1897 } else { 1898 //*out << Verbose(1) << "Not Adding: Wrong label order or distance too great." << endl; 1899 } 1900 } 1901 } 1902 } 1903 } 1904 } 1905 } 1906 1907 1908 1909 // 4. free the cell again 1910 for (int i=NumberCells;i--;) 1911 if (CellList[i] != NULL) { 1912 delete(CellList[i]); 1913 } 1914 Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList"); 1915 1916 // create the adjacency list per atom 1917 CreateListOfBondsPerAtom(out); 1918 1919 // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees, 1920 // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene 1921 // preferred over carbon bonds). Beforehand, we had picked the first mismatching partner, which lead to oxygenes with single instead of 1922 // double bonds as was expected. 1923 if (BondCount != 0) { 1924 NoCyclicBonds = 0; 1925 *out << Verbose(1) << "Correcting Bond degree of each bond ... "; 1926 do { 1927 No = 0; // No acts as breakup flag (if 1 we still continue) 1928 Walker = start; 1929 while (Walker->next != end) { // go through every atom 1930 Walker = Walker->next; 1931 // count valence of first partner 1932 NoBonds = 0; 1933 for(j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) 1934 NoBonds += ListOfBondsPerAtom[Walker->nr][j]->BondDegree; 1935 *out << Verbose(3) << "Walker " << *Walker << ": " << (int)Walker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl; 1936 if ((int)(Walker->type->NoValenceOrbitals) > NoBonds) { // we have a mismatch, check all bonding partners for mismatch 1937 Candidate = NULL; 1938 CandidateBondNo = -1; 1939 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through each of its bond partners 1940 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 1941 // count valence of second partner 1942 NoBonds = 0; 1943 for(j=0;j<NumberOfBondsPerAtom[OtherWalker->nr];j++) 1944 NoBonds += ListOfBondsPerAtom[OtherWalker->nr][j]->BondDegree; 1945 *out << Verbose(3) << "OtherWalker " << *OtherWalker << ": " << (int)OtherWalker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl; 1946 if ((int)(OtherWalker->type->NoValenceOrbitals) > NoBonds) { // check if possible candidate 1947 if ((Candidate == NULL) || (NumberOfBondsPerAtom[Candidate->nr] > NumberOfBondsPerAtom[OtherWalker->nr])) { // pick the one with fewer number of bonds first 1948 Candidate = OtherWalker; 1949 CandidateBondNo = i; 1950 *out << Verbose(3) << "New candidate is " << *Candidate << "." << endl; 1951 } 1952 } 1953 } 1954 if ((Candidate != NULL) && (CandidateBondNo != -1)) { 1955 ListOfBondsPerAtom[Walker->nr][CandidateBondNo]->BondDegree++; 1956 *out << Verbose(2) << "Increased bond degree for bond " << *ListOfBondsPerAtom[Walker->nr][CandidateBondNo] << "." << endl; 1957 } else 1958 *out << Verbose(2) << "Could not find correct degree for atom " << *Walker << "." << endl; 1959 FalseBondDegree++; 1960 } 1961 } 1962 } while (No); 1963 *out << " done." << endl; 1964 } else 1965 *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl; 1966 *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl; 1967 1968 // output bonds for debugging (if bond chain list was correctly installed) 1969 *out << Verbose(1) << endl << "From contents of bond chain list:"; 1970 bond *Binder = first; 1971 while(Binder->next != last) { 1972 Binder = Binder->next; 1973 *out << *Binder << "\t" << endl; 1974 } 1975 *out << endl; 1976 } else 1977 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl; 1978 *out << Verbose(0) << "End of CreateAdjacencyList." << endl; 1979 Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix"); 1980 1980 1981 1981 }; … … 1993 1993 MoleculeLeafClass * molecule::DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack) 1994 1994 { 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 } while (1);// (3)2058 2059 2060 2061 2062 2063 } while (1);// (2)2064 2065 2066 2067 2068 2069 2070 2071 2072 // (6)(Ancestor of Walker is not Root)2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 if (!BackStepping) {// coming from (8) want to go to (3)2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 // (11) Root is separation vertex,set Walker to Root and go to (4)2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 *out << " ===";2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 1995 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount); 1996 BackEdgeStack = new StackClass<bond *> (BondCount); 1997 MoleculeLeafClass *SubGraphs = new MoleculeLeafClass(NULL); 1998 MoleculeLeafClass *LeafWalker = SubGraphs; 1999 int CurrentGraphNr = 0, OldGraphNr; 2000 int ComponentNumber = 0; 2001 atom *Walker = NULL, *OtherAtom = NULL, *Root = start->next; 2002 bond *Binder = NULL; 2003 bool BackStepping = false; 2004 2005 *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl; 2006 2007 ResetAllBondsToUnused(); 2008 ResetAllAtomNumbers(); 2009 InitComponentNumbers(); 2010 BackEdgeStack->ClearStack(); 2011 while (Root != end) { // if there any atoms at all 2012 // (1) mark all edges unused, empty stack, set atom->GraphNr = 0 for all 2013 AtomStack->ClearStack(); 2014 2015 // put into new subgraph molecule and add this to list of subgraphs 2016 LeafWalker = new MoleculeLeafClass(LeafWalker); 2017 LeafWalker->Leaf = new molecule(elemente); 2018 LeafWalker->Leaf->AddCopyAtom(Root); 2019 2020 OldGraphNr = CurrentGraphNr; 2021 Walker = Root; 2022 do { // (10) 2023 do { // (2) set number and Lowpoint of Atom to i, increase i, push current atom 2024 if (!BackStepping) { // if we don't just return from (8) 2025 Walker->GraphNr = CurrentGraphNr; 2026 Walker->LowpointNr = CurrentGraphNr; 2027 *out << Verbose(1) << "Setting Walker[" << Walker->Name << "]'s number to " << Walker->GraphNr << " with Lowpoint " << Walker->LowpointNr << "." << endl; 2028 AtomStack->Push(Walker); 2029 CurrentGraphNr++; 2030 } 2031 do { // (3) if Walker has no unused egdes, go to (5) 2032 BackStepping = false; // reset backstepping flag for (8) 2033 if (Binder == NULL) // if we don't just return from (11), Binder is already set to next unused 2034 Binder = FindNextUnused(Walker); 2035 if (Binder == NULL) 2036 break; 2037 *out << Verbose(2) << "Current Unused Bond is " << *Binder << "." << endl; 2038 // (4) Mark Binder used, ... 2039 Binder->MarkUsed(black); 2040 OtherAtom = Binder->GetOtherAtom(Walker); 2041 *out << Verbose(2) << "(4) OtherAtom is " << OtherAtom->Name << "." << endl; 2042 if (OtherAtom->GraphNr != -1) { 2043 // (4a) ... if "other" atom has been visited (GraphNr != 0), set lowpoint to minimum of both, go to (3) 2044 Binder->Type = BackEdge; 2045 BackEdgeStack->Push(Binder); 2046 Walker->LowpointNr = ( Walker->LowpointNr < OtherAtom->GraphNr ) ? Walker->LowpointNr : OtherAtom->GraphNr; 2047 *out << Verbose(3) << "(4a) Visited: Setting Lowpoint of Walker[" << Walker->Name << "] to " << Walker->LowpointNr << "." << endl; 2048 } else { 2049 // (4b) ... otherwise set OtherAtom as Ancestor of Walker and Walker as OtherAtom, go to (2) 2050 Binder->Type = TreeEdge; 2051 OtherAtom->Ancestor = Walker; 2052 Walker = OtherAtom; 2053 *out << Verbose(3) << "(4b) Not Visited: OtherAtom[" << OtherAtom->Name << "]'s Ancestor is now " << OtherAtom->Ancestor->Name << ", Walker is OtherAtom " << OtherAtom->Name << "." << endl; 2054 break; 2055 } 2056 Binder = NULL; 2057 } while (1); // (3) 2058 if (Binder == NULL) { 2059 *out << Verbose(2) << "No more Unused Bonds." << endl; 2060 break; 2061 } else 2062 Binder = NULL; 2063 } while (1); // (2) 2064 2065 // if we came from backstepping, yet there were no more unused bonds, we end up here with no Ancestor, because Walker is Root! Then we are finished! 2066 if ((Walker == Root) && (Binder == NULL)) 2067 break; 2068 2069 // (5) if Ancestor of Walker is ... 2070 *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl; 2071 if (Walker->Ancestor->GraphNr != Root->GraphNr) { 2072 // (6) (Ancestor of Walker is not Root) 2073 if (Walker->LowpointNr < Walker->Ancestor->GraphNr) { 2074 // (6a) set Ancestor's Lowpoint number to minimum of of its Ancestor and itself, go to Step(8) 2075 Walker->Ancestor->LowpointNr = (Walker->Ancestor->LowpointNr < Walker->LowpointNr) ? Walker->Ancestor->LowpointNr : Walker->LowpointNr; 2076 *out << Verbose(2) << "(6) Setting Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s Lowpoint to " << Walker->Ancestor->LowpointNr << "." << endl; 2077 } else { 2078 // (7) (Ancestor of Walker is a separating vertex, remove all from stack till Walker (including), these and Ancestor form a component 2079 Walker->Ancestor->SeparationVertex = true; 2080 *out << Verbose(2) << "(7) Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s is a separating vertex, creating component." << endl; 2081 SetNextComponentNumber(Walker->Ancestor, ComponentNumber); 2082 *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Ancestor's Compont is " << ComponentNumber << "." << endl; 2083 SetNextComponentNumber(Walker, ComponentNumber); 2084 *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Compont is " << ComponentNumber << "." << endl; 2085 do { 2086 OtherAtom = AtomStack->PopLast(); 2087 LeafWalker->Leaf->AddCopyAtom(OtherAtom); 2088 SetNextComponentNumber(OtherAtom, ComponentNumber); 2089 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl; 2090 } while (OtherAtom != Walker); 2091 ComponentNumber++; 2092 } 2093 // (8) Walker becomes its Ancestor, go to (3) 2094 *out << Verbose(2) << "(8) Walker[" << Walker->Name << "] is now its Ancestor " << Walker->Ancestor->Name << ", backstepping. " << endl; 2095 Walker = Walker->Ancestor; 2096 BackStepping = true; 2097 } 2098 if (!BackStepping) { // coming from (8) want to go to (3) 2099 // (9) remove all from stack till Walker (including), these and Root form a component 2100 AtomStack->Output(out); 2101 SetNextComponentNumber(Root, ComponentNumber); 2102 *out << Verbose(3) << "(9) Root[" << Root->Name << "]'s Component is " << ComponentNumber << "." << endl; 2103 SetNextComponentNumber(Walker, ComponentNumber); 2104 *out << Verbose(3) << "(9) Walker[" << Walker->Name << "]'s Component is " << ComponentNumber << "." << endl; 2105 do { 2106 OtherAtom = AtomStack->PopLast(); 2107 LeafWalker->Leaf->AddCopyAtom(OtherAtom); 2108 SetNextComponentNumber(OtherAtom, ComponentNumber); 2109 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl; 2110 } while (OtherAtom != Walker); 2111 ComponentNumber++; 2112 2113 // (11) Root is separation vertex, set Walker to Root and go to (4) 2114 Walker = Root; 2115 Binder = FindNextUnused(Walker); 2116 *out << Verbose(1) << "(10) Walker is Root[" << Root->Name << "], next Unused Bond is " << Binder << "." << endl; 2117 if (Binder != NULL) { // Root is separation vertex 2118 *out << Verbose(1) << "(11) Root is a separation vertex." << endl; 2119 Walker->SeparationVertex = true; 2120 } 2121 } 2122 } while ((BackStepping) || (Binder != NULL)); // (10) halt only if Root has no unused edges 2123 2124 // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph 2125 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2126 LeafWalker->Leaf->Output(out); 2127 *out << endl; 2128 2129 // step on to next root 2130 while ((Root != end) && (Root->GraphNr != -1)) { 2131 //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl; 2132 if (Root->GraphNr != -1) // if already discovered, step on 2133 Root = Root->next; 2134 } 2135 } 2136 // set cyclic bond criterium on "same LP" basis 2137 Binder = first; 2138 while(Binder->next != last) { 2139 Binder = Binder->next; 2140 if (Binder->rightatom->LowpointNr == Binder->leftatom->LowpointNr) { // cyclic ?? 2141 Binder->Cyclic = true; 2142 NoCyclicBonds++; 2143 } 2144 } 2145 2146 2147 *out << Verbose(1) << "Final graph info for each atom is:" << endl; 2148 Walker = start; 2149 while (Walker->next != end) { 2150 Walker = Walker->next; 2151 *out << Verbose(2) << "Atom " << Walker->Name << " is " << ((Walker->SeparationVertex) ? "a" : "not a") << " separation vertex, components are "; 2152 OutputComponentNumber(out, Walker); 2153 *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl; 2154 } 2155 2156 *out << Verbose(1) << "Final graph info for each bond is:" << endl; 2157 Binder = first; 2158 while(Binder->next != last) { 2159 Binder = Binder->next; 2160 *out << Verbose(2) << ((Binder->Type == TreeEdge) ? "TreeEdge " : "BackEdge ") << *Binder << ": <"; 2161 *out << ((Binder->leftatom->SeparationVertex) ? "SP," : "") << "L" << Binder->leftatom->LowpointNr << " G" << Binder->leftatom->GraphNr << " Comp."; 2162 OutputComponentNumber(out, Binder->leftatom); 2163 *out << " === "; 2164 *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp."; 2165 OutputComponentNumber(out, Binder->rightatom); 2166 *out << ">." << endl; 2167 if (Binder->Cyclic) // cyclic ?? 2168 *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl; 2169 } 2170 2171 // free all and exit 2172 delete(AtomStack); 2173 *out << Verbose(0) << "End of DepthFirstSearchAnalysis" << endl; 2174 return SubGraphs; 2175 2175 }; 2176 2176 … … 2185 2185 * \todo BFS from the not-same-LP to find back to starting point of tributary cycle over more than one bond 2186 2186 */ 2187 void molecule::CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> * 2188 { 2189 2190 2191 2192 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount);// will hold the current ring2193 class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount);// contains all "touched" atoms (that need to be reset after BFS loop)2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 BFSStack->ClearStack();// start with empty BFS stack2218 2219 2220 2221 2222 do {// look for Root2223 2224 2225 2226 2227 2228 2187 void molecule::CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> * BackEdgeStack, int *&MinimumRingSize) 2188 { 2189 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CyclicStructureAnalysis: **PredecessorList"); 2190 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList"); 2191 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList"); 2192 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount); // will hold the current ring 2193 class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount); // contains all "touched" atoms (that need to be reset after BFS loop) 2194 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL; 2195 bond *Binder = NULL, *BackEdge = NULL; 2196 int RingSize, NumCycles, MinRingSize = -1; 2197 2198 // initialise each vertex as white with no predecessor, empty queue, color Root lightgray 2199 for (int i=AtomCount;i--;) { 2200 PredecessorList[i] = NULL; 2201 ShortestPathList[i] = -1; 2202 ColorList[i] = white; 2203 } 2204 2205 *out << Verbose(1) << "Back edge list - "; 2206 BackEdgeStack->Output(out); 2207 2208 *out << Verbose(1) << "Analysing cycles ... " << endl; 2209 NumCycles = 0; 2210 while (!BackEdgeStack->IsEmpty()) { 2211 BackEdge = BackEdgeStack->PopFirst(); 2212 // this is the target 2213 Root = BackEdge->leftatom; 2214 // this is the source point 2215 Walker = BackEdge->rightatom; 2216 ShortestPathList[Walker->nr] = 0; 2217 BFSStack->ClearStack(); // start with empty BFS stack 2218 BFSStack->Push(Walker); 2219 TouchedStack->Push(Walker); 2220 *out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl; 2221 OtherAtom = NULL; 2222 do { // look for Root 2223 Walker = BFSStack->PopFirst(); 2224 *out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl; 2225 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 2226 Binder = ListOfBondsPerAtom[Walker->nr][i]; 2227 if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder) 2228 OtherAtom = Binder->GetOtherAtom(Walker); 2229 2229 #ifdef ADDHYDROGEN 2230 2230 if (OtherAtom->type->Z != 1) { 2231 2231 #endif 2232 2233 2234 2235 2236 PredecessorList[OtherAtom->nr] = Walker;// Walker is the predecessor2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2232 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 2233 if (ColorList[OtherAtom->nr] == white) { 2234 TouchedStack->Push(OtherAtom); 2235 ColorList[OtherAtom->nr] = lightgray; 2236 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 2237 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 2238 *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " lightgray, its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl; 2239 //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance 2240 *out << Verbose(3) << "Putting OtherAtom into queue." << endl; 2241 BFSStack->Push(OtherAtom); 2242 //} 2243 } else { 2244 *out << Verbose(3) << "Not Adding, has already been visited." << endl; 2245 } 2246 if (OtherAtom == Root) 2247 break; 2248 2248 #ifdef ADDHYDROGEN 2249 2250 2251 2252 2249 } else { 2250 *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl; 2251 ColorList[OtherAtom->nr] = black; 2252 } 2253 2253 #endif 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 if (!OtherAtom->GetTrueFather()->IsCyclic)// if one bond in the loop is not marked as cyclic, we haven't found this cycle yet2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 TouchedStack->Push(OtherAtom);// last was wrongly popped2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 *out << Walker->Name << "with a length of " << RingSize << "." << endl << endl;2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 BFSStack->ClearStack();// start with empty BFS stack2333 2334 2335 2336 2337 while (OtherAtom != NULL) {// look for Root2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 PredecessorList[OtherAtom->nr] = Walker;// Walker is the predecessor2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2254 } else { 2255 *out << Verbose(2) << "Bond " << *Binder << " not Visiting, is the back edge." << endl; 2256 } 2257 } 2258 ColorList[Walker->nr] = black; 2259 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2260 if (OtherAtom == Root) { // if we have found the root, check whether this cycle wasn't already found beforehand 2261 // step through predecessor list 2262 while (OtherAtom != BackEdge->rightatom) { 2263 if (!OtherAtom->GetTrueFather()->IsCyclic) // if one bond in the loop is not marked as cyclic, we haven't found this cycle yet 2264 break; 2265 else 2266 OtherAtom = PredecessorList[OtherAtom->nr]; 2267 } 2268 if (OtherAtom == BackEdge->rightatom) { // if each atom in found cycle is cyclic, loop's been found before already 2269 *out << Verbose(3) << "This cycle was already found before, skipping and removing seeker from search." << endl;\ 2270 do { 2271 OtherAtom = TouchedStack->PopLast(); 2272 if (PredecessorList[OtherAtom->nr] == Walker) { 2273 *out << Verbose(4) << "Removing " << *OtherAtom << " from lists and stacks." << endl; 2274 PredecessorList[OtherAtom->nr] = NULL; 2275 ShortestPathList[OtherAtom->nr] = -1; 2276 ColorList[OtherAtom->nr] = white; 2277 BFSStack->RemoveItem(OtherAtom); 2278 } 2279 } while ((!TouchedStack->IsEmpty()) && (PredecessorList[OtherAtom->nr] == NULL)); 2280 TouchedStack->Push(OtherAtom); // last was wrongly popped 2281 OtherAtom = BackEdge->rightatom; // set to not Root 2282 } else 2283 OtherAtom = Root; 2284 } 2285 } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]))); 2286 2287 if (OtherAtom == Root) { 2288 // now climb back the predecessor list and thus find the cycle members 2289 NumCycles++; 2290 RingSize = 1; 2291 Root->GetTrueFather()->IsCyclic = true; 2292 *out << Verbose(1) << "Found ring contains: "; 2293 Walker = Root; 2294 while (Walker != BackEdge->rightatom) { 2295 *out << Walker->Name << " <-> "; 2296 Walker = PredecessorList[Walker->nr]; 2297 Walker->GetTrueFather()->IsCyclic = true; 2298 RingSize++; 2299 } 2300 *out << Walker->Name << " with a length of " << RingSize << "." << endl << endl; 2301 // walk through all and set MinimumRingSize 2302 Walker = Root; 2303 MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize; 2304 while (Walker != BackEdge->rightatom) { 2305 Walker = PredecessorList[Walker->nr]; 2306 if (RingSize < MinimumRingSize[Walker->GetTrueFather()->nr]) 2307 MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize; 2308 } 2309 if ((RingSize < MinRingSize) || (MinRingSize == -1)) 2310 MinRingSize = RingSize; 2311 } else { 2312 *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl; 2313 } 2314 2315 // now clean the lists 2316 while (!TouchedStack->IsEmpty()){ 2317 Walker = TouchedStack->PopFirst(); 2318 PredecessorList[Walker->nr] = NULL; 2319 ShortestPathList[Walker->nr] = -1; 2320 ColorList[Walker->nr] = white; 2321 } 2322 } 2323 if (MinRingSize != -1) { 2324 // go over all atoms 2325 Root = start; 2326 while(Root->next != end) { 2327 Root = Root->next; 2328 2329 if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is 2330 Walker = Root; 2331 ShortestPathList[Walker->nr] = 0; 2332 BFSStack->ClearStack(); // start with empty BFS stack 2333 BFSStack->Push(Walker); 2334 TouchedStack->Push(Walker); 2335 //*out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl; 2336 OtherAtom = Walker; 2337 while (OtherAtom != NULL) { // look for Root 2338 Walker = BFSStack->PopFirst(); 2339 //*out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl; 2340 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 2341 Binder = ListOfBondsPerAtom[Walker->nr][i]; 2342 if ((Binder != BackEdge) || (NumberOfBondsPerAtom[Walker->nr] == 1)) { // only walk along DFS spanning tree (otherwise we always find SP of 1 being backedge Binder), but terminal hydrogens may be connected via backedge, hence extra check 2343 OtherAtom = Binder->GetOtherAtom(Walker); 2344 //*out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 2345 if (ColorList[OtherAtom->nr] == white) { 2346 TouchedStack->Push(OtherAtom); 2347 ColorList[OtherAtom->nr] = lightgray; 2348 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 2349 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 2350 //*out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " lightgray, its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl; 2351 if (OtherAtom->GetTrueFather()->IsCyclic) { // if the other atom is connected to a ring 2352 MinimumRingSize[Root->GetTrueFather()->nr] = ShortestPathList[OtherAtom->nr]+MinimumRingSize[OtherAtom->GetTrueFather()->nr]; 2353 OtherAtom = NULL; //break; 2354 break; 2355 } else 2356 BFSStack->Push(OtherAtom); 2357 } else { 2358 //*out << Verbose(3) << "Not Adding, has already been visited." << endl; 2359 } 2360 } else { 2361 //*out << Verbose(3) << "Not Visiting, is a back edge." << endl; 2362 } 2363 } 2364 ColorList[Walker->nr] = black; 2365 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2366 } 2367 2368 // now clean the lists 2369 while (!TouchedStack->IsEmpty()){ 2370 Walker = TouchedStack->PopFirst(); 2371 PredecessorList[Walker->nr] = NULL; 2372 ShortestPathList[Walker->nr] = -1; 2373 ColorList[Walker->nr] = white; 2374 } 2375 } 2376 *out << Verbose(1) << "Minimum ring size of " << *Root << " is " << MinimumRingSize[Root->GetTrueFather()->nr] << "." << endl; 2377 } 2378 *out << Verbose(1) << "Minimum ring size is " << MinRingSize << ", over " << NumCycles << " cycles total." << endl; 2379 } else 2380 *out << Verbose(1) << "No rings were detected in the molecular structure." << endl; 2381 2382 Free((void **)&PredecessorList, "molecule::CyclicStructureAnalysis: **PredecessorList"); 2383 Free((void **)&ShortestPathList, "molecule::CyclicStructureAnalysis: **ShortestPathList"); 2384 Free((void **)&ColorList, "molecule::CyclicStructureAnalysis: **ColorList"); 2385 delete(BFSStack); 2386 2386 }; 2387 2387 … … 2393 2393 void molecule::SetNextComponentNumber(atom *vertex, int nr) 2394 2394 { 2395 2396 2397 2398 if (vertex->ComponentNr[i] == -1) {// check if not yet used2399 2400 2401 2402 2403 break;// breaking here will not cause error!2404 2405 2406 2407 2408 2395 int i=0; 2396 if (vertex != NULL) { 2397 for(;i<NumberOfBondsPerAtom[vertex->nr];i++) { 2398 if (vertex->ComponentNr[i] == -1) { // check if not yet used 2399 vertex->ComponentNr[i] = nr; 2400 break; 2401 } 2402 else if (vertex->ComponentNr[i] == nr) // if number is already present, don't add another time 2403 break; // breaking here will not cause error! 2404 } 2405 if (i == NumberOfBondsPerAtom[vertex->nr]) 2406 cerr << "Error: All Component entries are already occupied!" << endl; 2407 } else 2408 cerr << "Error: Given vertex is NULL!" << endl; 2409 2409 }; 2410 2410 … … 2414 2414 void molecule::OutputComponentNumber(ofstream *out, atom *vertex) 2415 2415 { 2416 2417 *out << vertex->ComponentNr[i] << "";2416 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2417 *out << vertex->ComponentNr[i] << " "; 2418 2418 }; 2419 2419 … … 2422 2422 void molecule::InitComponentNumbers() 2423 2423 { 2424 2425 2426 2427 2428 2429 2430 2431 2432 2424 atom *Walker = start; 2425 while(Walker->next != end) { 2426 Walker = Walker->next; 2427 if (Walker->ComponentNr != NULL) 2428 Free((void **)&Walker->ComponentNr, "molecule::InitComponentNumbers: **Walker->ComponentNr"); 2429 Walker->ComponentNr = (int *) Malloc(sizeof(int)*NumberOfBondsPerAtom[Walker->nr], "molecule::InitComponentNumbers: *Walker->ComponentNr"); 2430 for (int i=NumberOfBondsPerAtom[Walker->nr];i--;) 2431 Walker->ComponentNr[i] = -1; 2432 } 2433 2433 }; 2434 2434 … … 2439 2439 bond * molecule::FindNextUnused(atom *vertex) 2440 2440 { 2441 2442 2443 2444 2441 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2442 if (ListOfBondsPerAtom[vertex->nr][i]->IsUsed() == white) 2443 return(ListOfBondsPerAtom[vertex->nr][i]); 2444 return NULL; 2445 2445 }; 2446 2446 … … 2450 2450 void molecule::ResetAllBondsToUnused() 2451 2451 { 2452 2453 2454 2455 2456 2452 bond *Binder = first; 2453 while (Binder->next != last) { 2454 Binder = Binder->next; 2455 Binder->ResetUsed(); 2456 } 2457 2457 }; 2458 2458 … … 2461 2461 void molecule::ResetAllAtomNumbers() 2462 2462 { 2463 2464 2465 2466 Walker->GraphNr= -1;2467 2463 atom *Walker = start; 2464 while (Walker->next != end) { 2465 Walker = Walker->next; 2466 Walker->GraphNr = -1; 2467 } 2468 2468 }; 2469 2469 … … 2474 2474 void OutputAlreadyVisited(ofstream *out, int *list) 2475 2475 { 2476 2477 for(int i=1;i<=list[0];i++) *out << Verbose(0) << list[i] << "";2478 2476 *out << Verbose(4) << "Already Visited Bonds:\t"; 2477 for(int i=1;i<=list[0];i++) *out << Verbose(0) << list[i] << " "; 2478 *out << endl; 2479 2479 }; 2480 2480 … … 2482 2482 * The upper limit is 2483 2483 * \f[ 2484 * 2484 * n = N \cdot C^k 2485 2485 * \f] 2486 2486 * where \f$C=2^c\f$ and c is the maximum bond degree over N number of atoms. … … 2491 2491 int molecule::GuesstimateFragmentCount(ofstream *out, int order) 2492 2492 { 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2493 int c = 0; 2494 int FragmentCount; 2495 // get maximum bond degree 2496 atom *Walker = start; 2497 while (Walker->next != end) { 2498 Walker = Walker->next; 2499 c = (NumberOfBondsPerAtom[Walker->nr] > c) ? NumberOfBondsPerAtom[Walker->nr] : c; 2500 } 2501 FragmentCount = NoNonHydrogen*(1 << (c*order)); 2502 *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl; 2503 return FragmentCount; 2504 2504 }; 2505 2505 … … 2512 2512 bool molecule::ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet) 2513 2513 { 2514 2515 2516 2517 2518 2519 2520 2521 2522 CurrentSet.insert(AtomNr);// insert at end, hence in same order as in file!2523 2524 2525 2526 2527 2528 2529 2530 2531 2514 stringstream line; 2515 int AtomNr; 2516 int status = 0; 2517 2518 line.str(buffer); 2519 while (!line.eof()) { 2520 line >> AtomNr; 2521 if ((AtomNr >= 0) && (AtomNr < AtomCount)) { 2522 CurrentSet.insert(AtomNr); // insert at end, hence in same order as in file! 2523 status++; 2524 } // else it's "-1" or else and thus must not be added 2525 } 2526 *out << Verbose(1) << "The scanned KeySet is "; 2527 for(KeySet::iterator runner = CurrentSet.begin(); runner != CurrentSet.end(); runner++) { 2528 *out << (*runner) << "\t"; 2529 } 2530 *out << endl; 2531 return (status != 0); 2532 2532 }; 2533 2533 … … 2544 2544 bool molecule::ParseKeySetFile(ofstream *out, char *path, Graph *&FragmentList) 2545 2545 { 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 if ((strlen(buffer) > 0) && (ScanBufferIntoKeySet(out, buffer, CurrentSet))) {// if at least one valid atom was added, write config2570 testGraphInsert = FragmentList->insert(GraphPair (CurrentSet,pair<int,double>(NumberOfFragments++,1)));// store fragment number and current factor2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2546 bool status = true; 2547 ifstream InputFile; 2548 stringstream line; 2549 GraphTestPair testGraphInsert; 2550 int NumberOfFragments = 0; 2551 double TEFactor; 2552 char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename"); 2553 2554 if (FragmentList == NULL) { // check list pointer 2555 FragmentList = new Graph; 2556 } 2557 2558 // 1st pass: open file and read 2559 *out << Verbose(1) << "Parsing the KeySet file ... " << endl; 2560 sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, KEYSETFILE); 2561 InputFile.open(filename); 2562 if (InputFile != NULL) { 2563 // each line represents a new fragment 2564 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - *buffer"); 2565 // 1. parse keysets and insert into temp. graph 2566 while (!InputFile.eof()) { 2567 InputFile.getline(buffer, MAXSTRINGSIZE); 2568 KeySet CurrentSet; 2569 if ((strlen(buffer) > 0) && (ScanBufferIntoKeySet(out, buffer, CurrentSet))) { // if at least one valid atom was added, write config 2570 testGraphInsert = FragmentList->insert(GraphPair (CurrentSet,pair<int,double>(NumberOfFragments++,1))); // store fragment number and current factor 2571 if (!testGraphInsert.second) { 2572 cerr << "KeySet file must be corrupt as there are two equal key sets therein!" << endl; 2573 } 2574 } 2575 } 2576 // 2. Free and done 2577 InputFile.close(); 2578 InputFile.clear(); 2579 Free((void **)&buffer, "molecule::ParseKeySetFile - *buffer"); 2580 *out << Verbose(1) << "done." << endl; 2581 } else { 2582 *out << Verbose(1) << "File " << filename << " not found." << endl; 2583 status = false; 2584 } 2585 2586 // 2nd pass: open TEFactors file and read 2587 *out << Verbose(1) << "Parsing the TEFactors file ... " << endl; 2588 sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, TEFACTORSFILE); 2589 InputFile.open(filename); 2590 if (InputFile != NULL) { 2591 // 3. add found TEFactors to each keyset 2592 NumberOfFragments = 0; 2593 for(Graph::iterator runner = FragmentList->begin();runner != FragmentList->end(); runner++) { 2594 if (!InputFile.eof()) { 2595 InputFile >> TEFactor; 2596 (*runner).second.second = TEFactor; 2597 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl; 2598 } else { 2599 status = false; 2600 break; 2601 } 2602 } 2603 // 4. Free and done 2604 InputFile.close(); 2605 *out << Verbose(1) << "done." << endl; 2606 } else { 2607 *out << Verbose(1) << "File " << filename << " not found." << endl; 2608 status = false; 2609 } 2610 2611 // free memory 2612 Free((void **)&filename, "molecule::ParseKeySetFile - filename"); 2613 2614 return status; 2615 2615 }; 2616 2616 … … 2623 2623 bool molecule::StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path) 2624 2624 { 2625 2626 bool status =true;2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2625 ofstream output; 2626 bool status = true; 2627 string line; 2628 2629 // open KeySet file 2630 line = path; 2631 line.append("/"); 2632 line += FRAGMENTPREFIX; 2633 line += KEYSETFILE; 2634 output.open(line.c_str(), ios::out); 2635 *out << Verbose(1) << "Saving key sets of the total graph ... "; 2636 if(output != NULL) { 2637 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) { 2638 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 2639 if (sprinter != (*runner).first.begin()) 2640 output << "\t"; 2641 output << *sprinter; 2642 } 2643 output << endl; 2644 } 2645 *out << "done." << endl; 2646 } else { 2647 cerr << "Unable to open " << line << " for writing keysets!" << endl; 2648 status = false; 2649 } 2650 output.close(); 2651 output.clear(); 2652 2653 // open TEFactors file 2654 line = path; 2655 line.append("/"); 2656 line += FRAGMENTPREFIX; 2657 line += TEFACTORSFILE; 2658 output.open(line.c_str(), ios::out); 2659 *out << Verbose(1) << "Saving TEFactors of the total graph ... "; 2660 if(output != NULL) { 2661 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) 2662 output << (*runner).second.second << endl; 2663 *out << Verbose(1) << "done." << endl; 2664 } else { 2665 *out << Verbose(1) << "failed to open " << line << "." << endl; 2666 status = false; 2667 } 2668 output.close(); 2669 2670 return status; 2671 2671 }; 2672 2672 … … 2679 2679 bool molecule::StoreAdjacencyToFile(ofstream *out, char *path) 2680 2680 { 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2681 ofstream AdjacencyFile; 2682 atom *Walker = NULL; 2683 stringstream line; 2684 bool status = true; 2685 2686 line << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE; 2687 AdjacencyFile.open(line.str().c_str(), ios::out); 2688 *out << Verbose(1) << "Saving adjacency list ... "; 2689 if (AdjacencyFile != NULL) { 2690 Walker = start; 2691 while(Walker->next != end) { 2692 Walker = Walker->next; 2693 AdjacencyFile << Walker->nr << "\t"; 2694 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) 2695 AdjacencyFile << ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker)->nr << "\t"; 2696 AdjacencyFile << endl; 2697 } 2698 AdjacencyFile.close(); 2699 *out << Verbose(1) << "done." << endl; 2700 } else { 2701 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl; 2702 status = false; 2703 } 2704 2705 return status; 2706 2706 }; 2707 2707 … … 2714 2714 bool molecule::CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms) 2715 2715 { 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 int NonMatchNumber = 0;// will number of atoms with differing bond structure2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2716 ifstream File; 2717 stringstream filename; 2718 bool status = true; 2719 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 2720 2721 filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE; 2722 File.open(filename.str().c_str(), ios::out); 2723 *out << Verbose(1) << "Looking at bond structure stored in adjacency file and comparing to present one ... "; 2724 if (File != NULL) { 2725 // allocate storage structure 2726 int NonMatchNumber = 0; // will number of atoms with differing bond structure 2727 int *CurrentBonds = (int *) Malloc(sizeof(int)*8, "molecule::CheckAdjacencyFileAgainstMolecule - CurrentBonds"); // contains parsed bonds of current atom 2728 int CurrentBondsOfAtom; 2729 2730 // Parse the file line by line and count the bonds 2731 while (!File.eof()) { 2732 File.getline(buffer, MAXSTRINGSIZE); 2733 stringstream line; 2734 line.str(buffer); 2735 int AtomNr = -1; 2736 line >> AtomNr; 2737 CurrentBondsOfAtom = -1; // we count one too far due to line end 2738 // parse into structure 2739 if ((AtomNr >= 0) && (AtomNr < AtomCount)) { 2740 while (!line.eof()) 2741 line >> CurrentBonds[ ++CurrentBondsOfAtom ]; 2742 // compare against present bonds 2743 //cout << Verbose(2) << "Walker is " << *Walker << ", bond partners: "; 2744 if (CurrentBondsOfAtom == NumberOfBondsPerAtom[AtomNr]) { 2745 for(int i=0;i<NumberOfBondsPerAtom[AtomNr];i++) { 2746 int id = ListOfBondsPerAtom[AtomNr][i]->GetOtherAtom(ListOfAtoms[AtomNr])->nr; 2747 int j = 0; 2748 for (;(j<CurrentBondsOfAtom) && (CurrentBonds[j++] != id);); // check against all parsed bonds 2749 if (CurrentBonds[j-1] != id) { // no match ? Then mark in ListOfAtoms 2750 ListOfAtoms[AtomNr] = NULL; 2751 NonMatchNumber++; 2752 status = false; 2753 //out << "[" << id << "]\t"; 2754 } else { 2755 //out << id << "\t"; 2756 } 2757 } 2758 //out << endl; 2759 } else { 2760 *out << "Number of bonds for Atom " << *ListOfAtoms[AtomNr] << " does not match, parsed " << CurrentBondsOfAtom << " against " << NumberOfBondsPerAtom[AtomNr] << "." << endl; 2761 status = false; 2762 } 2763 } 2764 } 2765 File.close(); 2766 File.clear(); 2767 if (status) { // if equal we parse the KeySetFile 2768 *out << Verbose(1) << "done: Equal." << endl; 2769 status = true; 2770 } else 2771 *out << Verbose(1) << "done: Not equal by " << NonMatchNumber << " atoms." << endl; 2772 Free((void **)&CurrentBonds, "molecule::CheckAdjacencyFileAgainstMolecule - **CurrentBonds"); 2773 } else { 2774 *out << Verbose(1) << "Adjacency file not found." << endl; 2775 status = false; 2776 } 2777 *out << endl; 2778 Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 2779 2780 return status; 2781 2781 }; 2782 2782 … … 2792 2792 bool molecule::CheckOrderAtSite(ofstream *out, bool *AtomMask, Graph *GlobalKeySetList, int Order, int *MinimumRingSize, char *path) 2793 2793 { 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 if (AtomMask[AtomCount] == true)// break after one step2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 //*out << Verbose(2) << "Scanned " << lines-1 << " lines." << endl;// one endline too much2824 2825 2826 map<int, pair<double,int> > AdaptiveCriteriaList;// (Root No., (Value, Order)) !2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 No -= 1;// indices start at 1 in file, not 02842 2843 2844 2845 map<int,KeySet>::iterator marker = IndexKeySetList.find(No);// find keyset to Frag No.2846 if (marker != IndexKeySetList.end()) {// if found2847 Value *= 1 + MYEPSILON*(*((*marker).second.begin()));// in case of equal energies this makes em not equal without changing anything actually2848 2849 2850 2851 2852 if ((*PresentItem).second.second < FragOrder)// if order there is lower, update entry with higher-order term2853 //if ((*PresentItem).second.first < (*runner).first)// as higher-order terms are not always better, we skip this part (which would always include this site into adaptive increase)2854 {// if value is smaller, update value and order2855 2856 2857 *out << Verbose(2) << "Updated element (" <<(*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;2858 2859 *out << Verbose(2) << "Did not update element " <<(*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl;2860 2861 2862 *out << Verbose(2) << "Inserted element (" <<(*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 AtomMask[Walker->nr] = true;// include all (non-hydrogen) atoms2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 AtomMask[Walker->nr] = true;// include all (non-hydrogen) atoms2923 2924 2925 2926 2927 if ((Order == 0) && (AtomMask[AtomCount] == false))// single stepping, just check2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 *out << "";2940 2941 2942 2943 2944 2945 2946 2947 2794 atom *Walker = start; 2795 bool status = false; 2796 ifstream InputFile; 2797 2798 // initialize mask list 2799 for(int i=AtomCount;i--;) 2800 AtomMask[i] = false; 2801 2802 if (Order < 0) { // adaptive increase of BondOrder per site 2803 if (AtomMask[AtomCount] == true) // break after one step 2804 return false; 2805 // parse the EnergyPerFragment file 2806 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckOrderAtSite: *buffer"); 2807 sprintf(buffer, "%s/%s%s.dat", path, FRAGMENTPREFIX, ENERGYPERFRAGMENT); 2808 InputFile.open(buffer, ios::in); 2809 if ((InputFile != NULL) && (GlobalKeySetList != NULL)) { 2810 // transmorph graph keyset list into indexed KeySetList 2811 map<int,KeySet> IndexKeySetList; 2812 for(Graph::iterator runner = GlobalKeySetList->begin(); runner != GlobalKeySetList->end(); runner++) { 2813 IndexKeySetList.insert( pair<int,KeySet>(runner->second.first,runner->first) ); 2814 } 2815 int lines = 0; 2816 // count the number of lines, i.e. the number of fragments 2817 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines 2818 InputFile.getline(buffer, MAXSTRINGSIZE); 2819 while(!InputFile.eof()) { 2820 InputFile.getline(buffer, MAXSTRINGSIZE); 2821 lines++; 2822 } 2823 //*out << Verbose(2) << "Scanned " << lines-1 << " lines." << endl; // one endline too much 2824 InputFile.clear(); 2825 InputFile.seekg(ios::beg); 2826 map<int, pair<double,int> > AdaptiveCriteriaList; // (Root No., (Value, Order)) ! 2827 int No, FragOrder; 2828 double Value; 2829 // each line represents a fragment root (Atom::nr) id and its energy contribution 2830 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines 2831 InputFile.getline(buffer, MAXSTRINGSIZE); 2832 while(!InputFile.eof()) { 2833 InputFile.getline(buffer, MAXSTRINGSIZE); 2834 if (strlen(buffer) > 2) { 2835 //*out << Verbose(2) << "Scanning: " << buffer << endl; 2836 stringstream line(buffer); 2837 line >> FragOrder; 2838 line >> ws >> No; 2839 line >> ws >> Value; // skip time entry 2840 line >> ws >> Value; 2841 No -= 1; // indices start at 1 in file, not 0 2842 //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl; 2843 2844 // clean the list of those entries that have been superceded by higher order terms already 2845 map<int,KeySet>::iterator marker = IndexKeySetList.find(No); // find keyset to Frag No. 2846 if (marker != IndexKeySetList.end()) { // if found 2847 Value *= 1 + MYEPSILON*(*((*marker).second.begin())); // in case of equal energies this makes em not equal without changing anything actually 2848 // as the smallest number in each set has always been the root (we use global id to keep the doubles away), seek smallest and insert into AtomMask 2849 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) )); 2850 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 2851 if (!InsertedElement.second) { // this root is already present 2852 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term 2853 //if ((*PresentItem).second.first < (*runner).first) // as higher-order terms are not always better, we skip this part (which would always include this site into adaptive increase) 2854 { // if value is smaller, update value and order 2855 (*PresentItem).second.first = fabs(Value); 2856 (*PresentItem).second.second = FragOrder; 2857 *out << Verbose(2) << "Updated element (" << (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl; 2858 } else { 2859 *out << Verbose(2) << "Did not update element " << (*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl; 2860 } 2861 } else { 2862 *out << Verbose(2) << "Inserted element (" << (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl; 2863 } 2864 } else { 2865 *out << Verbose(1) << "No Fragment under No. " << No << "found." << endl; 2866 } 2867 } 2868 } 2869 // then map back onto (Value, (Root Nr., Order)) (i.e. sorted by value to pick the highest ones) 2870 map<double, pair<int,int> > FinalRootCandidates; 2871 *out << Verbose(1) << "Root candidate list is: " << endl; 2872 for(map<int, pair<double,int> >::iterator runner = AdaptiveCriteriaList.begin(); runner != AdaptiveCriteriaList.end(); runner++) { 2873 Walker = FindAtom((*runner).first); 2874 if (Walker != NULL) { 2875 //if ((*runner).second.second >= Walker->AdaptiveOrder) { // only insert if this is an "active" root site for the current order 2876 if (!Walker->MaxOrder) { 2877 *out << Verbose(2) << "(" << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "])" << endl; 2878 FinalRootCandidates.insert( make_pair( (*runner).second.first, pair<int,int>((*runner).first, (*runner).second.second) ) ); 2879 } else { 2880 *out << Verbose(2) << "Excluding (" << *Walker << ", " << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "]), as it has reached its maximum order." << endl; 2881 } 2882 } else { 2883 cerr << "Atom No. " << (*runner).second.first << " was not found in this molecule." << endl; 2884 } 2885 } 2886 // pick the ones still below threshold and mark as to be adaptively updated 2887 for(map<double, pair<int,int> >::iterator runner = FinalRootCandidates.upper_bound(pow(10.,Order)); runner != FinalRootCandidates.end(); runner++) { 2888 No = (*runner).second.first; 2889 Walker = FindAtom(No); 2890 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) { 2891 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 2892 AtomMask[No] = true; 2893 status = true; 2894 //} else 2895 //*out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", however MinimumRingSize of " << MinimumRingSize[Walker->nr] << " does not allow further adaptive increase." << endl; 2896 } 2897 // close and done 2898 InputFile.close(); 2899 InputFile.clear(); 2900 } else { 2901 cerr << "Unable to parse " << buffer << " file, incrementing all." << endl; 2902 while (Walker->next != end) { 2903 Walker = Walker->next; 2904 #ifdef ADDHYDROGEN 2905 if (Walker->type->Z != 1) // skip hydrogen 2906 #endif 2907 { 2908 AtomMask[Walker->nr] = true; // include all (non-hydrogen) atoms 2909 status = true; 2910 } 2911 } 2912 } 2913 Free((void **)&buffer, "molecule::CheckOrderAtSite: *buffer"); 2914 // pick a given number of highest values and set AtomMask 2915 } else { // global increase of Bond Order 2916 while (Walker->next != end) { 2917 Walker = Walker->next; 2918 #ifdef ADDHYDROGEN 2919 if (Walker->type->Z != 1) // skip hydrogen 2920 #endif 2921 { 2922 AtomMask[Walker->nr] = true; // include all (non-hydrogen) atoms 2923 if ((Order != 0) && (Walker->AdaptiveOrder < Order)) // && (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr])) 2924 status = true; 2925 } 2926 } 2927 if ((Order == 0) && (AtomMask[AtomCount] == false)) // single stepping, just check 2928 status = true; 2929 2930 if (!status) { 2931 if (Order == 0) 2932 *out << Verbose(1) << "Single stepping done." << endl; 2933 else 2934 *out << Verbose(1) << "Order at every site is already equal or above desired order " << Order << "." << endl; 2935 } 2936 } 2937 2938 // print atom mask for debugging 2939 *out << " "; 2940 for(int i=0;i<AtomCount;i++) 2941 *out << (i % 10); 2942 *out << endl << "Atom mask is: "; 2943 for(int i=0;i<AtomCount;i++) 2944 *out << (AtomMask[i] ? "t" : "f"); 2945 *out << endl; 2946 2947 return status; 2948 2948 }; 2949 2949 … … 2955 2955 bool molecule::CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex) 2956 2956 { 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2957 element *runner = elemente->start; 2958 int AtomNo = 0; 2959 atom *Walker = NULL; 2960 2961 if (SortIndex != NULL) { 2962 *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl; 2963 return false; 2964 } 2965 SortIndex = (int *) Malloc(sizeof(int)*AtomCount, "molecule::FragmentMolecule: *SortIndex"); 2966 for(int i=AtomCount;i--;) 2967 SortIndex[i] = -1; 2968 while (runner->next != elemente->end) { // go through every element 2969 runner = runner->next; 2970 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 2971 Walker = start; 2972 while (Walker->next != end) { // go through every atom of this element 2973 Walker = Walker->next; 2974 if (Walker->type->Z == runner->Z) // if this atom fits to element 2975 SortIndex[Walker->nr] = AtomNo++; 2976 } 2977 } 2978 } 2979 return true; 2980 2980 }; 2981 2981 … … 2986 2986 y contribution", and that's why this consciously not done in the following loop) 2987 2987 * -# in a loop over all subgraphs 2988 * 2989 * 2988 * -# calls FragmentBOSSANOVA with this RootStack and within the subgraph molecule structure 2989 * -# creates molecule (fragment)s from the returned keysets (StoreFragmentFromKeySet) 2990 2990 * -# combines the generated molecule lists from all subgraphs 2991 2991 * -# saves to disk: fragment configs, adjacency, orderatsite, keyset files … … 3000 3000 int molecule::FragmentMolecule(ofstream *out, int Order, config *configuration) 3001 3001 { 3002 3003 3004 3005 3006 3007 MoleculeLeafClass *Subgraphs = NULL;// list of subgraphs from DFS analysis3008 3009 3010 3011 3012 3013 3014 Graph TotalGraph;// graph with all keysets however local numbers3015 3016 3017 3018 3019 3020 3002 MoleculeListClass *BondFragments = NULL; 3003 int *SortIndex = NULL; 3004 int *MinimumRingSize = new int[AtomCount]; 3005 int FragmentCounter; 3006 MoleculeLeafClass *MolecularWalker = NULL; 3007 MoleculeLeafClass *Subgraphs = NULL; // list of subgraphs from DFS analysis 3008 fstream File; 3009 bool FragmentationToDo = true; 3010 class StackClass<bond *> *BackEdgeStack = NULL, *LocalBackEdgeStack = NULL; 3011 bool CheckOrder = false; 3012 Graph **FragmentList = NULL; 3013 Graph *ParsedFragmentList = NULL; 3014 Graph TotalGraph; // graph with all keysets however local numbers 3015 int TotalNumberOfKeySets = 0; 3016 atom **ListOfAtoms = NULL; 3017 atom ***ListOfLocalAtoms = NULL; 3018 bool *AtomMask = NULL; 3019 3020 *out << endl; 3021 3021 #ifdef ADDHYDROGEN 3022 3022 *out << Verbose(0) << "I will treat hydrogen special and saturate dangling bonds with it." << endl; 3023 3023 #else 3024 3024 *out << Verbose(0) << "Hydrogen is treated just like the rest of the lot." << endl; 3025 3025 #endif 3026 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 Subgraphs->next->FillBondStructureFromReference(out, this, (FragmentCounter = 0), ListOfLocalAtoms, false);// we want to keep the created ListOfLocalAtoms3045 3046 3047 3048 3049 3050 3051 3052 3053 // 3054 // 3055 // 3056 // 3057 // 3058 // 3059 // 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 FragmentationToDo = false;// if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards3083 3084 3085 AtomMask[AtomCount] = true;// last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite()3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 //MolecularWalker->Leaf->OutputListOfBonds(out);// output ListOfBondsPerAtom for debugging3096 3097 3098 3099 3100 3101 3102 3103 FragmentCounter++;// next fragment list3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 //if (FragmentationToDo) {// we should always store the fragments again as coordination might have changed slightly without changing bond structure3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 //*out << Verbose(1) << "No fragments to store." << endl;3179 3180 3181 return ((int)(!FragmentationToDo)+1);// 1 - continue, 2 - stop (no fragmentation occured)3027 // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++ 3028 3029 // ===== 1. Check whether bond structure is same as stored in files ==== 3030 3031 // fill the adjacency list 3032 CreateListOfBondsPerAtom(out); 3033 3034 // create lookup table for Atom::nr 3035 FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount); 3036 3037 // === compare it with adjacency file === 3038 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 3039 Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms"); 3040 3041 // ===== 2. perform a DFS analysis to gather info on cyclic structure and a list of disconnected subgraphs ===== 3042 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack); 3043 // fill the bond structure of the individually stored subgraphs 3044 Subgraphs->next->FillBondStructureFromReference(out, this, (FragmentCounter = 0), ListOfLocalAtoms, false); // we want to keep the created ListOfLocalAtoms 3045 // analysis of the cycles (print rings, get minimum cycle length) for each subgraph 3046 for(int i=AtomCount;i--;) 3047 MinimumRingSize[i] = AtomCount; 3048 MolecularWalker = Subgraphs; 3049 FragmentCounter = 0; 3050 while (MolecularWalker->next != NULL) { 3051 MolecularWalker = MolecularWalker->next; 3052 LocalBackEdgeStack = new StackClass<bond *> (MolecularWalker->Leaf->BondCount); 3053 // // check the list of local atoms for debugging 3054 // *out << Verbose(0) << "ListOfLocalAtoms for this subgraph is:" << endl; 3055 // for (int i=0;i<AtomCount;i++) 3056 // if (ListOfLocalAtoms[FragmentCounter][i] == NULL) 3057 // *out << "\tNULL"; 3058 // else 3059 // *out << "\t" << ListOfLocalAtoms[FragmentCounter][i]->Name; 3060 *out << Verbose(0) << "Gathering local back edges for subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3061 MolecularWalker->Leaf->PickLocalBackEdges(out, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack); 3062 *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3063 MolecularWalker->Leaf->CyclicStructureAnalysis(out, LocalBackEdgeStack, MinimumRingSize); 3064 *out << Verbose(0) << "Done with Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3065 delete(LocalBackEdgeStack); 3066 } 3067 3068 // ===== 3. if structure still valid, parse key set file and others ===== 3069 FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList); 3070 3071 // ===== 4. check globally whether there's something to do actually (first adaptivity check) 3072 FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath); 3073 3074 // =================================== Begin of FRAGMENTATION =============================== 3075 // ===== 6a. assign each keyset to its respective subgraph ===== 3076 Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true); 3077 3078 // ===== 6b. prepare and go into the adaptive (Order<0), single-step (Order==0) or incremental (Order>0) cycle 3079 KeyStack *RootStack = new KeyStack[Subgraphs->next->Count()]; 3080 AtomMask = new bool[AtomCount+1]; 3081 AtomMask[AtomCount] = false; 3082 FragmentationToDo = false; // if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards 3083 while ((CheckOrder = CheckOrderAtSite(out, AtomMask, ParsedFragmentList, Order, MinimumRingSize, configuration->configpath))) { 3084 FragmentationToDo = FragmentationToDo || CheckOrder; 3085 AtomMask[AtomCount] = true; // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite() 3086 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 3087 Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0)); 3088 3089 // ===== 7. fill the bond fragment list ===== 3090 FragmentCounter = 0; 3091 MolecularWalker = Subgraphs; 3092 while (MolecularWalker->next != NULL) { 3093 MolecularWalker = MolecularWalker->next; 3094 *out << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl; 3095 //MolecularWalker->Leaf->OutputListOfBonds(out); // output ListOfBondsPerAtom for debugging 3096 if (MolecularWalker->Leaf->first->next != MolecularWalker->Leaf->last) { 3097 // call BOSSANOVA method 3098 *out << Verbose(0) << endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= " << endl; 3099 MolecularWalker->Leaf->FragmentBOSSANOVA(out, FragmentList[FragmentCounter], RootStack[FragmentCounter], MinimumRingSize); 3100 } else { 3101 cerr << "Subgraph " << MolecularWalker << " has no atoms!" << endl; 3102 } 3103 FragmentCounter++; // next fragment list 3104 } 3105 } 3106 delete[](RootStack); 3107 delete[](AtomMask); 3108 delete(ParsedFragmentList); 3109 delete[](MinimumRingSize); 3110 3111 3112 // ==================================== End of FRAGMENTATION ============================================ 3113 3114 // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf) 3115 Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph); 3116 3117 // free subgraph memory again 3118 FragmentCounter = 0; 3119 if (Subgraphs != NULL) { 3120 while (Subgraphs->next != NULL) { 3121 Subgraphs = Subgraphs->next; 3122 delete(FragmentList[FragmentCounter++]); 3123 delete(Subgraphs->previous); 3124 } 3125 delete(Subgraphs); 3126 } 3127 Free((void **)&FragmentList, "molecule::FragmentMolecule - **FragmentList"); 3128 3129 // ===== 8b. gather keyset lists (graphs) from all subgraphs and transform into MoleculeListClass ===== 3130 //if (FragmentationToDo) { // we should always store the fragments again as coordination might have changed slightly without changing bond structure 3131 // allocate memory for the pointer array and transmorph graphs into full molecular fragments 3132 BondFragments = new MoleculeListClass(); 3133 int k=0; 3134 for(Graph::iterator runner = TotalGraph.begin(); runner != TotalGraph.end(); runner++) { 3135 KeySet test = (*runner).first; 3136 *out << "Fragment No." << (*runner).second.first << " with TEFactor " << (*runner).second.second << "." << endl; 3137 BondFragments->insert(StoreFragmentFromKeySet(out, test, configuration)); 3138 k++; 3139 } 3140 *out << k << "/" << BondFragments->ListOfMolecules.size() << " fragments generated from the keysets." << endl; 3141 3142 // ===== 9. Save fragments' configuration and keyset files et al to disk === 3143 if (BondFragments->ListOfMolecules.size() != 0) { 3144 // create the SortIndex from BFS labels to order in the config file 3145 CreateMappingLabelsToConfigSequence(out, SortIndex); 3146 3147 *out << Verbose(1) << "Writing " << BondFragments->ListOfMolecules.size() << " possible bond fragmentation configs" << endl; 3148 if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex)) 3149 *out << Verbose(1) << "All configs written." << endl; 3150 else 3151 *out << Verbose(1) << "Some config writing failed." << endl; 3152 3153 // store force index reference file 3154 BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex); 3155 3156 // store keysets file 3157 StoreKeySetFile(out, TotalGraph, configuration->configpath); 3158 3159 // store Adjacency file 3160 StoreAdjacencyToFile(out, configuration->configpath); 3161 3162 // store Hydrogen saturation correction file 3163 BondFragments->AddHydrogenCorrection(out, configuration->configpath); 3164 3165 // store adaptive orders into file 3166 StoreOrderAtSiteFile(out, configuration->configpath); 3167 3168 // restore orbital and Stop values 3169 CalculateOrbitals(*configuration); 3170 3171 // free memory for bond part 3172 *out << Verbose(1) << "Freeing bond memory" << endl; 3173 delete(FragmentList); // remove bond molecule from memory 3174 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3175 } else 3176 *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl; 3177 //} else 3178 // *out << Verbose(1) << "No fragments to store." << endl; 3179 *out << Verbose(0) << "End of bond fragmentation." << endl; 3180 3181 return ((int)(!FragmentationToDo)+1); // 1 - continue, 2 - stop (no fragmentation occured) 3182 3182 }; 3183 3183 … … 3192 3192 bool molecule::PickLocalBackEdges(ofstream *out, atom **ListOfLocalAtoms, class StackClass<bond *> *&ReferenceStack, class StackClass<bond *> *&LocalStack) 3193 3193 { 3194 3195 3196 3197 3198 3199 3200 bond *FirstBond = Binder;// mark the first bond, so that we don't loop through the stack indefinitely3201 3202 3203 3204 do {// go through all bonds and push local ones3205 Walker = ListOfLocalAtoms[Binder->leftatom->nr];// get one atom in the reference molecule3206 3207 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {// go through the local list of bonds3208 3209 3210 3211 3212 3213 3214 3215 Binder = ReferenceStack->PopFirst();// loop the stack for next item3216 3217 3218 3219 3220 3194 bool status = true; 3195 if (ReferenceStack->IsEmpty()) { 3196 cerr << "ReferenceStack is empty!" << endl; 3197 return false; 3198 } 3199 bond *Binder = ReferenceStack->PopFirst(); 3200 bond *FirstBond = Binder; // mark the first bond, so that we don't loop through the stack indefinitely 3201 atom *Walker = NULL, *OtherAtom = NULL; 3202 ReferenceStack->Push(Binder); 3203 3204 do { // go through all bonds and push local ones 3205 Walker = ListOfLocalAtoms[Binder->leftatom->nr]; // get one atom in the reference molecule 3206 if (Walker != NULL) // if this Walker exists in the subgraph ... 3207 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through the local list of bonds 3208 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 3209 if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond 3210 LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]); 3211 *out << Verbose(3) << "Found local edge " << *(ListOfBondsPerAtom[Walker->nr][i]) << "." << endl; 3212 break; 3213 } 3214 } 3215 Binder = ReferenceStack->PopFirst(); // loop the stack for next item 3216 *out << Verbose(3) << "Current candidate edge " << Binder << "." << endl; 3217 ReferenceStack->Push(Binder); 3218 } while (FirstBond != Binder); 3219 3220 return status; 3221 3221 }; 3222 3222 … … 3229 3229 bool molecule::StoreOrderAtSiteFile(ofstream *out, char *path) 3230 3230 { 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3231 stringstream line; 3232 ofstream file; 3233 3234 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE; 3235 file.open(line.str().c_str()); 3236 *out << Verbose(1) << "Writing OrderAtSite " << ORDERATSITEFILE << " ... " << endl; 3237 if (file != NULL) { 3238 atom *Walker = start; 3239 while (Walker->next != end) { 3240 Walker = Walker->next; 3241 file << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << endl; 3242 *out << Verbose(2) << "Storing: " << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << "." << endl; 3243 } 3244 file.close(); 3245 *out << Verbose(1) << "done." << endl; 3246 return true; 3247 } else { 3248 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl; 3249 return false; 3250 } 3251 3251 }; 3252 3252 … … 3260 3260 bool molecule::ParseOrderAtSiteFromFile(ofstream *out, char *path) 3261 3261 { 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 if (AtomNr != -1) {// test whether we really parsed something (this is necessary, otherwise last atom is set twice and to 0 on second time)3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3262 unsigned char *OrderArray = (unsigned char *) Malloc(sizeof(unsigned char)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 3263 bool *MaxArray = (bool *) Malloc(sizeof(bool)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *MaxArray"); 3264 bool status; 3265 int AtomNr, value; 3266 stringstream line; 3267 ifstream file; 3268 3269 *out << Verbose(1) << "Begin of ParseOrderAtSiteFromFile" << endl; 3270 for(int i=AtomCount;i--;) 3271 OrderArray[i] = 0; 3272 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE; 3273 file.open(line.str().c_str()); 3274 if (file != NULL) { 3275 for (int i=AtomCount;i--;) { // initialise with 0 3276 OrderArray[i] = 0; 3277 MaxArray[i] = 0; 3278 } 3279 while (!file.eof()) { // parse from file 3280 AtomNr = -1; 3281 file >> AtomNr; 3282 if (AtomNr != -1) { // test whether we really parsed something (this is necessary, otherwise last atom is set twice and to 0 on second time) 3283 file >> value; 3284 OrderArray[AtomNr] = value; 3285 file >> value; 3286 MaxArray[AtomNr] = value; 3287 //*out << Verbose(2) << "AtomNr " << AtomNr << " with order " << (int)OrderArray[AtomNr] << " and max order set to " << (int)MaxArray[AtomNr] << "." << endl; 3288 } 3289 } 3290 atom *Walker = start; 3291 while (Walker->next != end) { // fill into atom classes 3292 Walker = Walker->next; 3293 Walker->AdaptiveOrder = OrderArray[Walker->nr]; 3294 Walker->MaxOrder = MaxArray[Walker->nr]; 3295 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl; 3296 } 3297 file.close(); 3298 *out << Verbose(1) << "done." << endl; 3299 status = true; 3300 } else { 3301 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl; 3302 status = false; 3303 } 3304 Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 3305 Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray"); 3306 3307 *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl; 3308 return status; 3309 3309 }; 3310 3310 … … 3317 3317 void molecule::CreateListOfBondsPerAtom(ofstream *out) 3318 3318 { 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3319 bond *Binder = NULL; 3320 atom *Walker = NULL; 3321 int TotalDegree; 3322 *out << Verbose(1) << "Begin of Creating ListOfBondsPerAtom: AtomCount = " << AtomCount << "\tBondCount = " << BondCount << "\tNoNonBonds = " << NoNonBonds << "." << endl; 3323 3324 // re-allocate memory 3325 *out << Verbose(2) << "(Re-)Allocating memory." << endl; 3326 if (ListOfBondsPerAtom != NULL) { 3327 for(int i=AtomCount;i--;) 3328 Free((void **)&ListOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom[i]"); 3329 Free((void **)&ListOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom"); 3330 } 3331 if (NumberOfBondsPerAtom != NULL) 3332 Free((void **)&NumberOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: NumberOfBondsPerAtom"); 3333 ListOfBondsPerAtom = (bond ***) Malloc(sizeof(bond **)*AtomCount, "molecule::CreateListOfBondsPerAtom: ***ListOfBondsPerAtom"); 3334 NumberOfBondsPerAtom = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfBondsPerAtom: *NumberOfBondsPerAtom"); 3335 3336 // reset bond counts per atom 3337 for(int i=AtomCount;i--;) 3338 NumberOfBondsPerAtom[i] = 0; 3339 // count bonds per atom 3340 Binder = first; 3341 while (Binder->next != last) { 3342 Binder = Binder->next; 3343 NumberOfBondsPerAtom[Binder->leftatom->nr]++; 3344 NumberOfBondsPerAtom[Binder->rightatom->nr]++; 3345 } 3346 for(int i=AtomCount;i--;) { 3347 // allocate list of bonds per atom 3348 ListOfBondsPerAtom[i] = (bond **) Malloc(sizeof(bond *)*NumberOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: **ListOfBondsPerAtom[]"); 3349 // clear the list again, now each NumberOfBondsPerAtom marks current free field 3350 NumberOfBondsPerAtom[i] = 0; 3351 } 3352 // fill the list 3353 Binder = first; 3354 while (Binder->next != last) { 3355 Binder = Binder->next; 3356 ListOfBondsPerAtom[Binder->leftatom->nr][NumberOfBondsPerAtom[Binder->leftatom->nr]++] = Binder; 3357 ListOfBondsPerAtom[Binder->rightatom->nr][NumberOfBondsPerAtom[Binder->rightatom->nr]++] = Binder; 3358 } 3359 3360 // output list for debugging 3361 *out << Verbose(3) << "ListOfBondsPerAtom for each atom:" << endl; 3362 Walker = start; 3363 while (Walker->next != end) { 3364 Walker = Walker->next; 3365 *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: "; 3366 TotalDegree = 0; 3367 for (int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) { 3368 *out << *ListOfBondsPerAtom[Walker->nr][j] << "\t"; 3369 TotalDegree += ListOfBondsPerAtom[Walker->nr][j]->BondDegree; 3370 } 3371 *out << " -- TotalDegree: " << TotalDegree << endl; 3372 } 3373 *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl; 3374 3374 }; 3375 3375 … … 3388 3388 void molecule::BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem) 3389 3389 { 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 if (AddedAtomList[Root->nr] == NULL)// add Root if not yet present3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 PredecessorList[OtherAtom->nr] = Walker;// Walker is the predecessor3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 } else {// this code should actually never come into play (all white atoms are not yet present in BondMolecule, that's why they are white in the first place)3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3390 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::BreadthFirstSearchAdd: **PredecessorList"); 3391 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::BreadthFirstSearchAdd: *ShortestPathList"); 3392 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::BreadthFirstSearchAdd: *ColorList"); 3393 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount); 3394 atom *Walker = NULL, *OtherAtom = NULL; 3395 bond *Binder = NULL; 3396 3397 // add Root if not done yet 3398 AtomStack->ClearStack(); 3399 if (AddedAtomList[Root->nr] == NULL) // add Root if not yet present 3400 AddedAtomList[Root->nr] = Mol->AddCopyAtom(Root); 3401 AtomStack->Push(Root); 3402 3403 // initialise each vertex as white with no predecessor, empty queue, color Root lightgray 3404 for (int i=AtomCount;i--;) { 3405 PredecessorList[i] = NULL; 3406 ShortestPathList[i] = -1; 3407 if (AddedAtomList[i] != NULL) // mark already present atoms (i.e. Root and maybe others) as visited 3408 ColorList[i] = lightgray; 3409 else 3410 ColorList[i] = white; 3411 } 3412 ShortestPathList[Root->nr] = 0; 3413 3414 // and go on ... Queue always contains all lightgray vertices 3415 while (!AtomStack->IsEmpty()) { 3416 // we have to pop the oldest atom from stack. This keeps the atoms on the stack always of the same ShortestPath distance. 3417 // e.g. if current atom is 2, push to end of stack are of length 3, but first all of length 2 would be popped. They again 3418 // append length of 3 (their neighbours). Thus on stack we have always atoms of a certain length n at bottom of stack and 3419 // followed by n+1 till top of stack. 3420 Walker = AtomStack->PopFirst(); // pop oldest added 3421 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl; 3422 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 3423 Binder = ListOfBondsPerAtom[Walker->nr][i]; 3424 if (Binder != NULL) { // don't look at bond equal NULL 3425 OtherAtom = Binder->GetOtherAtom(Walker); 3426 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 3427 if (ColorList[OtherAtom->nr] == white) { 3428 if (Binder != Bond) // let other atom white if it's via Root bond. In case it's cyclic it has to be reached again (yet Root is from OtherAtom already black, thus no problem) 3429 ColorList[OtherAtom->nr] = lightgray; 3430 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 3431 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 3432 *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " " << ((ColorList[OtherAtom->nr] == white) ? "white" : "lightgray") << ", its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl; 3433 if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance 3434 *out << Verbose(3); 3435 if (AddedAtomList[OtherAtom->nr] == NULL) { // add if it's not been so far 3436 AddedAtomList[OtherAtom->nr] = Mol->AddCopyAtom(OtherAtom); 3437 *out << "Added OtherAtom " << OtherAtom->Name; 3438 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3439 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3440 AddedBondList[Binder->nr]->Type = Binder->Type; 3441 *out << " and bond " << *(AddedBondList[Binder->nr]) << ", "; 3442 } else { // this code should actually never come into play (all white atoms are not yet present in BondMolecule, that's why they are white in the first place) 3443 *out << "Not adding OtherAtom " << OtherAtom->Name; 3444 if (AddedBondList[Binder->nr] == NULL) { 3445 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3446 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3447 AddedBondList[Binder->nr]->Type = Binder->Type; 3448 *out << ", added Bond " << *(AddedBondList[Binder->nr]); 3449 } else 3450 *out << ", not added Bond "; 3451 } 3452 *out << ", putting OtherAtom into queue." << endl; 3453 AtomStack->Push(OtherAtom); 3454 } else { // out of bond order, then replace 3455 if ((AddedAtomList[OtherAtom->nr] == NULL) && (Binder->Cyclic)) 3456 ColorList[OtherAtom->nr] = white; // unmark if it has not been queued/added, to make it available via its other bonds (cyclic) 3457 if (Binder == Bond) 3458 *out << Verbose(3) << "Not Queueing, is the Root bond"; 3459 else if (ShortestPathList[OtherAtom->nr] >= BondOrder) 3460 *out << Verbose(3) << "Not Queueing, is out of Bond Count of " << BondOrder; 3461 if (!Binder->Cyclic) 3462 *out << ", is not part of a cyclic bond, saturating bond with Hydrogen." << endl; 3463 if (AddedBondList[Binder->nr] == NULL) { 3464 if ((AddedAtomList[OtherAtom->nr] != NULL)) { // .. whether we add or saturate 3465 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3466 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3467 AddedBondList[Binder->nr]->Type = Binder->Type; 3468 } else { 3469 3469 #ifdef ADDHYDROGEN 3470 3471 3470 if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem)) 3471 exit(1); 3472 3472 #endif 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3473 } 3474 } 3475 } 3476 } else { 3477 *out << Verbose(3) << "Not Adding, has already been visited." << endl; 3478 // This has to be a cyclic bond, check whether it's present ... 3479 if (AddedBondList[Binder->nr] == NULL) { 3480 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 3481 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3482 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3483 AddedBondList[Binder->nr]->Type = Binder->Type; 3484 } else { // if it's root bond it has to broken (otherwise we would not create the fragments) 3485 3485 #ifdef ADDHYDROGEN 3486 3487 3486 if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem)) 3487 exit(1); 3488 3488 #endif 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3489 } 3490 } 3491 } 3492 } 3493 } 3494 ColorList[Walker->nr] = black; 3495 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 3496 } 3497 Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList"); 3498 Free((void **)&ShortestPathList, "molecule::BreadthFirstSearchAdd: **ShortestPathList"); 3499 Free((void **)&ColorList, "molecule::BreadthFirstSearchAdd: **ColorList"); 3500 delete(AtomStack); 3501 3501 }; 3502 3502 … … 3512 3512 bool molecule::BuildInducedSubgraph(ofstream *out, const molecule *Father) 3513 3513 { 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 *out << Verbose(4) << "Son["<< Walker->father->nr <<"] of " << Walker->father <<" is " << ParentList[Walker->father->nr] << "." << endl;3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3514 atom *Walker = NULL, *OtherAtom = NULL; 3515 bool status = true; 3516 atom **ParentList = (atom **) Malloc(sizeof(atom *)*Father->AtomCount, "molecule::BuildInducedSubgraph: **ParentList"); 3517 3518 *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl; 3519 3520 // reset parent list 3521 *out << Verbose(3) << "Resetting ParentList." << endl; 3522 for (int i=Father->AtomCount;i--;) 3523 ParentList[i] = NULL; 3524 3525 // fill parent list with sons 3526 *out << Verbose(3) << "Filling Parent List." << endl; 3527 Walker = start; 3528 while (Walker->next != end) { 3529 Walker = Walker->next; 3530 ParentList[Walker->father->nr] = Walker; 3531 // Outputting List for debugging 3532 *out << Verbose(4) << "Son["<< Walker->father->nr <<"] of " << Walker->father << " is " << ParentList[Walker->father->nr] << "." << endl; 3533 } 3534 3535 // check each entry of parent list and if ok (one-to-and-onto matching) create bonds 3536 *out << Verbose(3) << "Creating bonds." << endl; 3537 Walker = Father->start; 3538 while (Walker->next != Father->end) { 3539 Walker = Walker->next; 3540 if (ParentList[Walker->nr] != NULL) { 3541 if (ParentList[Walker->nr]->father != Walker) { 3542 status = false; 3543 } else { 3544 for (int i=0;i<Father->NumberOfBondsPerAtom[Walker->nr];i++) { 3545 OtherAtom = Father->ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 3546 if (ParentList[OtherAtom->nr] != NULL) { // if otheratom is also a father of an atom on this molecule, create the bond 3547 *out << Verbose(4) << "Endpoints of Bond " << Father->ListOfBondsPerAtom[Walker->nr][i] << " are both present: " << ParentList[Walker->nr]->Name << " and " << ParentList[OtherAtom->nr]->Name << "." << endl; 3548 AddBond(ParentList[Walker->nr], ParentList[OtherAtom->nr], Father->ListOfBondsPerAtom[Walker->nr][i]->BondDegree); 3549 } 3550 } 3551 } 3552 } 3553 } 3554 3555 Free((void **)&ParentList, "molecule::BuildInducedSubgraph: **ParentList"); 3556 *out << Verbose(2) << "End of BuildInducedSubgraph." << endl; 3557 return status; 3558 3558 }; 3559 3559 … … 3567 3567 int molecule::LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList) 3568 3568 { 3569 3570 3571 3572 3573 SP = -1; //0;// not -1, so that Root is never removed3574 3575 3576 3577 3578 if (ShortestPathList[(*runner)] > SP) {// remove the oldest one with longest shortest path3579 3580 3581 3582 3583 3584 3569 atom *Runner = NULL; 3570 int SP, Removal; 3571 3572 *out << Verbose(2) << "Looking for removal candidate." << endl; 3573 SP = -1; //0; // not -1, so that Root is never removed 3574 Removal = -1; 3575 for (KeySet::iterator runner = Leaf->begin(); runner != Leaf->end(); runner++) { 3576 Runner = FindAtom((*runner)); 3577 if (Runner->type->Z != 1) { // skip all those added hydrogens when re-filling snake stack 3578 if (ShortestPathList[(*runner)] > SP) { // remove the oldest one with longest shortest path 3579 SP = ShortestPathList[(*runner)]; 3580 Removal = (*runner); 3581 } 3582 } 3583 } 3584 return Removal; 3585 3585 }; 3586 3586 … … 3595 3595 molecule * molecule::StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem) 3596 3596 { 3597 3598 3599 3600 3601 3602 3603 // 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 FatherOfRunner = FindAtom((*runner));// find the id3617 3618 3619 3620 3621 3622 // 3623 3624 3625 3626 3627 3628 if (SonList[FatherOfRunner->nr] != NULL) {// check if this, our father, is present in list3629 3630 3631 3632 // 3633 3634 // 3635 3636 // 3637 // 3638 3639 // 3640 3641 3642 // 3643 3644 3645 3646 // 3597 atom *Runner = NULL, *FatherOfRunner = NULL, *OtherFather = NULL; 3598 atom **SonList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::StoreFragmentFromStack: **SonList"); 3599 molecule *Leaf = new molecule(elemente); 3600 bool LonelyFlag = false; 3601 int size; 3602 3603 // *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl; 3604 3605 Leaf->BondDistance = BondDistance; 3606 for(int i=NDIM*2;i--;) 3607 Leaf->cell_size[i] = cell_size[i]; 3608 3609 // initialise SonList (indicates when we need to replace a bond with hydrogen instead) 3610 for(int i=AtomCount;i--;) 3611 SonList[i] = NULL; 3612 3613 // first create the minimal set of atoms from the KeySet 3614 size = 0; 3615 for(KeySet::iterator runner = Leaflet.begin(); runner != Leaflet.end(); runner++) { 3616 FatherOfRunner = FindAtom((*runner)); // find the id 3617 SonList[FatherOfRunner->nr] = Leaf->AddCopyAtom(FatherOfRunner); 3618 size++; 3619 } 3620 3621 // create the bonds between all: Make it an induced subgraph and add hydrogen 3622 // *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl; 3623 Runner = Leaf->start; 3624 while (Runner->next != Leaf->end) { 3625 Runner = Runner->next; 3626 LonelyFlag = true; 3627 FatherOfRunner = Runner->father; 3628 if (SonList[FatherOfRunner->nr] != NULL) { // check if this, our father, is present in list 3629 // create all bonds 3630 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father 3631 OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner); 3632 // *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather; 3633 if (SonList[OtherFather->nr] != NULL) { 3634 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 3635 if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba) 3636 // *out << Verbose(3) << "Adding Bond: "; 3637 // *out << 3638 Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree); 3639 // *out << "." << endl; 3640 //NumBonds[Runner->nr]++; 3641 } else { 3642 // *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl; 3643 } 3644 LonelyFlag = false; 3645 } else { 3646 // *out << ", who has no son in this fragment molecule." << endl; 3647 3647 #ifdef ADDHYDROGEN 3648 3649 3650 3648 //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl; 3649 if(!Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem)) 3650 exit(1); 3651 3651 #endif 3652 3653 3654 3655 3656 3657 3658 3659 3660 3652 //NumBonds[Runner->nr] += ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree; 3653 } 3654 } 3655 } else { 3656 *out << Verbose(0) << "ERROR: Son " << Runner->Name << " has father " << FatherOfRunner->Name << " but its entry in SonList is " << SonList[FatherOfRunner->nr] << "!" << endl; 3657 } 3658 if ((LonelyFlag) && (size > 1)) { 3659 *out << Verbose(0) << *Runner << "has got bonds only to hydrogens!" << endl; 3660 } 3661 3661 #ifdef ADDHYDROGEN 3662 3663 3662 while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen 3663 Runner = Runner->next; 3664 3664 #endif 3665 3666 3667 3668 3669 // 3670 3665 } 3666 Leaf->CreateListOfBondsPerAtom(out); 3667 //Leaflet->Leaf->ScanForPeriodicCorrection(out); 3668 Free((void **)&SonList, "molecule::StoreFragmentFromStack: **SonList"); 3669 // *out << Verbose(1) << "End of StoreFragmentFromKeyset." << endl; 3670 return Leaf; 3671 3671 }; 3672 3672 … … 3674 3674 */ 3675 3675 struct UniqueFragments { 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3676 config *configuration; 3677 atom *Root; 3678 Graph *Leaflet; 3679 KeySet *FragmentSet; 3680 int ANOVAOrder; 3681 int FragmentCounter; 3682 int CurrentIndex; 3683 double TEFactor; 3684 int *ShortestPathList; 3685 bool **UsedList; 3686 bond **BondsPerSPList; 3687 int *BondsPerSPCount; 3688 3688 }; 3689 3689 3690 3690 /** From a given set of Bond sorted by Shortest Path distance, create all possible fragments of size \a SetDimension. 3691 3691 * -# loops over every possible combination (2^dimension of edge set) 3692 * 3693 * 3692 * -# inserts current set, if there's still space left 3693 * -# yes: calls SPFragmentGenerator with structure, created new edge list and size respective to root dist 3694 3694 ance+1 3695 * 3696 * 3695 * -# no: stores fragment into keyset list by calling InsertFragmentIntoGraph 3696 * -# removes all items added into the snake stack (in UniqueFragments structure) added during level (root 3697 3697 distance) and current set 3698 3698 * \param *out output stream for debugging … … 3704 3704 void molecule::SPFragmentGenerator(ofstream *out, struct UniqueFragments *FragmentSearch, int RootDistance, bond **BondsSet, int SetDimension, int SubOrder) 3705 3705 { 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 *out << Verbose(1+verbosity) << "We are " << RootDistance << " away from Root, which is " << *FragmentSearch->Root << ", SubOrder is " << SubOrder << ", SetDimension is " << SetDimension << " and this means " <<NumCombinations-1 << " combination(s)." << endl;3726 3727 3728 3729 for (TouchedIndex=SubOrder+1;TouchedIndex--;)// empty touched list3730 3731 3732 3733 3734 3735 for (int i=1;i<NumCombinations;i++) {// sweep through all power set combinations (skip empty set!)3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 for (int j=0;j<SetDimension;j++) {// pull out every bit by shifting3746 bit = ((i & (1 << j)) != 0);// mask the bit for the j-th bond3747 if (bit) {// if bit is set, we add this bond partner3748 OtherWalker = BondsSet[j]->rightatom;// rightatom is always the one more distant, i.e. the one to add3749 3750 3751 3752 3753 TouchedList[TouchedIndex++] = OtherWalker->nr;// note as added3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 if (SubOrder > 1) {// Due to Added above we have to check extra whether we're not already reaching beyond the desired Order3769 3770 SP = RootDistance+1;// this is the next level3771 3772 3773 Binder = FragmentSearch->BondsPerSPList[2*SP];// start node for this level3774 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) {// compare to end node of this level3775 3776 3777 if (Binder->Contains(TouchedList[k]))// if we added this very endpiece3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 if (Binder->leftatom->nr == TouchedList[k])// leftatom is always the close one3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3706 atom *OtherWalker = NULL; 3707 int verbosity = 0; //FragmentSearch->ANOVAOrder-SubOrder; 3708 int NumCombinations; 3709 bool bit; 3710 int bits, TouchedIndex, SubSetDimension, SP, Added; 3711 int Removal; 3712 int SpaceLeft; 3713 int *TouchedList = (int *) Malloc(sizeof(int)*(SubOrder+1), "molecule::SPFragmentGenerator: *TouchedList"); 3714 bond *Binder = NULL; 3715 bond **BondsList = NULL; 3716 KeySetTestPair TestKeySetInsert; 3717 3718 NumCombinations = 1 << SetDimension; 3719 3720 // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen 3721 // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder 3722 // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden 3723 3724 *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl; 3725 *out << Verbose(1+verbosity) << "We are " << RootDistance << " away from Root, which is " << *FragmentSearch->Root << ", SubOrder is " << SubOrder << ", SetDimension is " << SetDimension << " and this means " << NumCombinations-1 << " combination(s)." << endl; 3726 3727 // initialised touched list (stores added atoms on this level) 3728 *out << Verbose(1+verbosity) << "Clearing touched list." << endl; 3729 for (TouchedIndex=SubOrder+1;TouchedIndex--;) // empty touched list 3730 TouchedList[TouchedIndex] = -1; 3731 TouchedIndex = 0; 3732 3733 // create every possible combination of the endpieces 3734 *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl; 3735 for (int i=1;i<NumCombinations;i++) { // sweep through all power set combinations (skip empty set!) 3736 // count the set bit of i 3737 bits = 0; 3738 for (int j=SetDimension;j--;) 3739 bits += (i & (1 << j)) >> j; 3740 3741 *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl; 3742 if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue 3743 // --1-- add this set of the power set of bond partners to the snake stack 3744 Added = 0; 3745 for (int j=0;j<SetDimension;j++) { // pull out every bit by shifting 3746 bit = ((i & (1 << j)) != 0); // mask the bit for the j-th bond 3747 if (bit) { // if bit is set, we add this bond partner 3748 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add 3749 //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl; 3750 *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl; 3751 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 3752 if (TestKeySetInsert.second) { 3753 TouchedList[TouchedIndex++] = OtherWalker->nr; // note as added 3754 Added++; 3755 } else { 3756 *out << Verbose(2+verbosity) << "This was item was already present in the keyset." << endl; 3757 } 3758 //FragmentSearch->UsedList[OtherWalker->nr][i] = true; 3759 //} 3760 } else { 3761 *out << Verbose(2+verbosity) << "Not adding." << endl; 3762 } 3763 } 3764 3765 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore 3766 if (SpaceLeft > 0) { 3767 *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl; 3768 if (SubOrder > 1) { // Due to Added above we have to check extra whether we're not already reaching beyond the desired Order 3769 // --2-- look at all added end pieces of this combination, construct bond subsets and sweep through a power set of these by recursion 3770 SP = RootDistance+1; // this is the next level 3771 // first count the members in the subset 3772 SubSetDimension = 0; 3773 Binder = FragmentSearch->BondsPerSPList[2*SP]; // start node for this level 3774 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) { // compare to end node of this level 3775 Binder = Binder->next; 3776 for (int k=TouchedIndex;k--;) { 3777 if (Binder->Contains(TouchedList[k])) // if we added this very endpiece 3778 SubSetDimension++; 3779 } 3780 } 3781 // then allocate and fill the list 3782 BondsList = (bond **) Malloc(sizeof(bond *)*SubSetDimension, "molecule::SPFragmentGenerator: **BondsList"); 3783 SubSetDimension = 0; 3784 Binder = FragmentSearch->BondsPerSPList[2*SP]; 3785 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) { 3786 Binder = Binder->next; 3787 for (int k=0;k<TouchedIndex;k++) { 3788 if (Binder->leftatom->nr == TouchedList[k]) // leftatom is always the close one 3789 BondsList[SubSetDimension++] = Binder; 3790 } 3791 } 3792 *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl; 3793 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 3794 Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList"); 3795 } 3796 } else { 3797 // --2-- otherwise store the complete fragment 3798 *out << Verbose(1+verbosity) << "Enough items on stack for a fragment!" << endl; 3799 // store fragment as a KeySet 3800 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: "; 3801 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3802 *out << (*runner) << " "; 3803 *out << endl; 3804 //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet)) 3805 //*out << Verbose(0) << "ERROR: The found fragment is not a connected subgraph!" << endl; 3806 InsertFragmentIntoGraph(out, FragmentSearch); 3807 //Removal = LookForRemovalCandidate(out, FragmentSearch->FragmentSet, FragmentSearch->ShortestPathList); 3808 //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration); 3809 } 3810 3811 // --3-- remove all added items in this level from snake stack 3812 *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl; 3813 for(int j=0;j<TouchedIndex;j++) { 3814 Removal = TouchedList[j]; 3815 *out << Verbose(2+verbosity) << "Removing item nr. " << Removal << " from snake stack." << endl; 3816 FragmentSearch->FragmentSet->erase(Removal); 3817 TouchedList[j] = -1; 3818 } 3819 *out << Verbose(2) << "Remaining local nr.s on snake stack are: "; 3820 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3821 *out << (*runner) << " "; 3822 *out << endl; 3823 TouchedIndex = 0; // set Index to 0 for list of atoms added on this level 3824 } else { 3825 *out << Verbose(2+verbosity) << "More atoms to add for this set (" << bits << ") than space left on stack " << SubOrder << ", skipping this set." << endl; 3826 } 3827 } 3828 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 3829 *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl; 3830 3830 }; 3831 3831 … … 3838 3838 bool molecule::CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment) 3839 3839 { 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3840 atom *Walker = NULL, *Walker2 = NULL; 3841 bool BondStatus = false; 3842 int size; 3843 3844 *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl; 3845 *out << Verbose(2) << "Disconnected atom: "; 3846 3847 // count number of atoms in graph 3848 size = 0; 3849 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) 3850 size++; 3851 if (size > 1) 3852 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) { 3853 Walker = FindAtom(*runner); 3854 BondStatus = false; 3855 for(KeySet::iterator runners = Fragment->begin(); runners != Fragment->end(); runners++) { 3856 Walker2 = FindAtom(*runners); 3857 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) { 3858 if (ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker) == Walker2) { 3859 BondStatus = true; 3860 break; 3861 } 3862 if (BondStatus) 3863 break; 3864 } 3865 } 3866 if (!BondStatus) { 3867 *out << (*Walker) << endl; 3868 return false; 3869 } 3870 } 3871 else { 3872 *out << "none." << endl; 3873 return true; 3874 } 3875 *out << "none." << endl; 3876 3877 *out << Verbose(1) << "End of CheckForConnectedSubgraph" << endl; 3878 3879 return true; 3880 3880 } 3881 3881 … … 3897 3897 int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet) 3898 3898 { 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 CurrentEdge = FragmentSearch.BondsPerSPList[2*SP];/// start of this SP level's list3940 while (CurrentEdge->next != FragmentSearch.BondsPerSPList[2*SP+1]) {/// end of this SP level's list3941 3942 3943 Walker = CurrentEdge->rightatom;// rightatom is always the one more distant3944 Predecessor = CurrentEdge->leftatom;// ... and leftatom is predecessor3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 ) {// skip hydrogens and restrict to fragment3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 for(int i=1;i<Order;i++) {// skip the root edge in the printing3982 3983 3984 3985 3986 3987 3988 3989 3990 // creating fragments with the found edge sets(may be done in reverse order, faster)3991 SP = -1;// the Root <-> Root edge must be subtracted!3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next;// on SP level 0 there's only the root bond4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 3899 int SP, AtomKeyNr; 3900 atom *Walker = NULL, *OtherWalker = NULL, *Predecessor = NULL; 3901 bond *Binder = NULL; 3902 bond *CurrentEdge = NULL; 3903 bond **BondsList = NULL; 3904 int RootKeyNr = FragmentSearch.Root->GetTrueFather()->nr; 3905 int Counter = FragmentSearch.FragmentCounter; 3906 int RemainingWalkers; 3907 3908 *out << endl; 3909 *out << Verbose(0) << "Begin of PowerSetGenerator with order " << Order << " at Root " << *FragmentSearch.Root << "." << endl; 3910 3911 // prepare Label and SP arrays of the BFS search 3912 FragmentSearch.ShortestPathList[FragmentSearch.Root->nr] = 0; 3913 3914 // prepare root level (SP = 0) and a loop bond denoting Root 3915 for (int i=1;i<Order;i++) 3916 FragmentSearch.BondsPerSPCount[i] = 0; 3917 FragmentSearch.BondsPerSPCount[0] = 1; 3918 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 3919 add(Binder, FragmentSearch.BondsPerSPList[1]); 3920 3921 // do a BFS search to fill the SP lists and label the found vertices 3922 // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into 3923 // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning 3924 // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth 3925 // (EdgeinSPLevel) of this tree ... 3926 // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence 3927 // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction. 3928 *out << endl; 3929 *out << Verbose(0) << "Starting BFS analysis ..." << endl; 3930 for (SP = 0; SP < (Order-1); SP++) { 3931 *out << Verbose(1) << "New SP level reached: " << SP << ", creating new SP list with " << FragmentSearch.BondsPerSPCount[SP] << " item(s)"; 3932 if (SP > 0) { 3933 *out << ", old level closed with " << FragmentSearch.BondsPerSPCount[SP-1] << " item(s)." << endl; 3934 FragmentSearch.BondsPerSPCount[SP] = 0; 3935 } else 3936 *out << "." << endl; 3937 3938 RemainingWalkers = FragmentSearch.BondsPerSPCount[SP]; 3939 CurrentEdge = FragmentSearch.BondsPerSPList[2*SP]; /// start of this SP level's list 3940 while (CurrentEdge->next != FragmentSearch.BondsPerSPList[2*SP+1]) { /// end of this SP level's list 3941 CurrentEdge = CurrentEdge->next; 3942 RemainingWalkers--; 3943 Walker = CurrentEdge->rightatom; // rightatom is always the one more distant 3944 Predecessor = CurrentEdge->leftatom; // ... and leftatom is predecessor 3945 AtomKeyNr = Walker->nr; 3946 *out << Verbose(0) << "Current Walker is: " << *Walker << " with nr " << Walker->nr << " and SP of " << SP << ", with " << RemainingWalkers << " remaining walkers on this level." << endl; 3947 // check for new sp level 3948 // go through all its bonds 3949 *out << Verbose(1) << "Going through all bonds of Walker." << endl; 3950 for (int i=0;i<NumberOfBondsPerAtom[AtomKeyNr];i++) { 3951 Binder = ListOfBondsPerAtom[AtomKeyNr][i]; 3952 OtherWalker = Binder->GetOtherAtom(Walker); 3953 if ((RestrictedKeySet.find(OtherWalker->nr) != RestrictedKeySet.end()) 3954 #ifdef ADDHYDROGEN 3955 && (OtherWalker->type->Z != 1) 3956 #endif 3957 ) { // skip hydrogens and restrict to fragment 3958 *out << Verbose(2) << "Current partner is " << *OtherWalker << " with nr " << OtherWalker->nr << " in bond " << *Binder << "." << endl; 3959 // set the label if not set (and push on root stack as well) 3960 if ((OtherWalker != Predecessor) && (OtherWalker->GetTrueFather()->nr > RootKeyNr)) { // only pass through those with label bigger than Root's 3961 FragmentSearch.ShortestPathList[OtherWalker->nr] = SP+1; 3962 *out << Verbose(3) << "Set Shortest Path to " << FragmentSearch.ShortestPathList[OtherWalker->nr] << "." << endl; 3963 // add the bond in between to the SP list 3964 Binder = new bond(Walker, OtherWalker); // create a new bond in such a manner, that bond::rightatom is always the one more distant 3965 add(Binder, FragmentSearch.BondsPerSPList[2*(SP+1)+1]); 3966 FragmentSearch.BondsPerSPCount[SP+1]++; 3967 *out << Verbose(3) << "Added its bond to SP list, having now " << FragmentSearch.BondsPerSPCount[SP+1] << " item(s)." << endl; 3968 } else { 3969 if (OtherWalker != Predecessor) 3970 *out << Verbose(3) << "Not passing on, as index of " << *OtherWalker << " " << OtherWalker->GetTrueFather()->nr << " is smaller than that of Root " << RootKeyNr << "." << endl; 3971 else 3972 *out << Verbose(3) << "This is my predecessor " << *Predecessor << "." << endl; 3973 } 3974 } else *out << Verbose(2) << "Is not in the restricted keyset or skipping hydrogen " << *OtherWalker << "." << endl; 3975 } 3976 } 3977 } 3978 3979 // outputting all list for debugging 3980 *out << Verbose(0) << "Printing all found lists." << endl; 3981 for(int i=1;i<Order;i++) { // skip the root edge in the printing 3982 Binder = FragmentSearch.BondsPerSPList[2*i]; 3983 *out << Verbose(1) << "Current SP level is " << i << "." << endl; 3984 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 3985 Binder = Binder->next; 3986 *out << Verbose(2) << *Binder << endl; 3987 } 3988 } 3989 3990 // creating fragments with the found edge sets (may be done in reverse order, faster) 3991 SP = -1; // the Root <-> Root edge must be subtracted! 3992 for(int i=Order;i--;) { // sum up all found edges 3993 Binder = FragmentSearch.BondsPerSPList[2*i]; 3994 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 3995 Binder = Binder->next; 3996 SP ++; 3997 } 3998 } 3999 *out << Verbose(0) << "Total number of edges is " << SP << "." << endl; 4000 if (SP >= (Order-1)) { 4001 // start with root (push on fragment stack) 4002 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl; 4003 FragmentSearch.FragmentSet->clear(); 4004 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl; 4005 // prepare the subset and call the generator 4006 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList"); 4007 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next; // on SP level 0 there's only the root bond 4008 4009 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order); 4010 4011 Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList"); 4012 } else { 4013 *out << Verbose(0) << "Not enough total number of edges to build " << Order << "-body fragments." << endl; 4014 } 4015 4016 // as FragmentSearch structure is used only once, we don't have to clean it anymore 4017 // remove root from stack 4018 *out << Verbose(0) << "Removing root again from stack." << endl; 4019 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4020 4021 // free'ing the bonds lists 4022 *out << Verbose(0) << "Free'ing all found lists. and resetting index lists" << endl; 4023 for(int i=Order;i--;) { 4024 *out << Verbose(1) << "Current SP level is " << i << ": "; 4025 Binder = FragmentSearch.BondsPerSPList[2*i]; 4026 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 4027 Binder = Binder->next; 4028 // *out << "Removing atom " << Binder->leftatom->nr << " and " << Binder->rightatom->nr << "." << endl; // make sure numbers are local 4029 FragmentSearch.ShortestPathList[Binder->leftatom->nr] = -1; 4030 FragmentSearch.ShortestPathList[Binder->rightatom->nr] = -1; 4031 } 4032 // delete added bonds 4033 cleanup(FragmentSearch.BondsPerSPList[2*i], FragmentSearch.BondsPerSPList[2*i+1]); 4034 // also start and end node 4035 *out << "cleaned." << endl; 4036 } 4037 4038 // return list 4039 *out << Verbose(0) << "End of PowerSetGenerator." << endl; 4040 return (FragmentSearch.FragmentCounter - Counter); 4041 4041 }; 4042 4042 … … 4049 4049 void molecule::ScanForPeriodicCorrection(ofstream *out) 4050 4050 { 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 unlink(Binder);// unlink bond4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 ColorList[Walker->nr] = black;// mark as explored4106 4107 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {// go through all binding partners4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4051 bond *Binder = NULL; 4052 bond *OtherBinder = NULL; 4053 atom *Walker = NULL; 4054 atom *OtherWalker = NULL; 4055 double *matrix = ReturnFullMatrixforSymmetric(cell_size); 4056 enum Shading *ColorList = NULL; 4057 double tmp; 4058 Vector Translationvector; 4059 //class StackClass<atom *> *CompStack = NULL; 4060 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount); 4061 bool flag = true; 4062 4063 *out << Verbose(2) << "Begin of ScanForPeriodicCorrection." << endl; 4064 4065 ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::ScanForPeriodicCorrection: *ColorList"); 4066 while (flag) { 4067 // remove bonds that are beyond bonddistance 4068 for(int i=NDIM;i--;) 4069 Translationvector.x[i] = 0.; 4070 // scan all bonds 4071 Binder = first; 4072 flag = false; 4073 while ((!flag) && (Binder->next != last)) { 4074 Binder = Binder->next; 4075 for (int i=NDIM;i--;) { 4076 tmp = fabs(Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]); 4077 //*out << Verbose(3) << "Checking " << i << "th distance of " << *Binder->leftatom << " to " << *Binder->rightatom << ": " << tmp << "." << endl; 4078 if (tmp > BondDistance) { 4079 OtherBinder = Binder->next; // note down binding partner for later re-insertion 4080 unlink(Binder); // unlink bond 4081 *out << Verbose(2) << "Correcting at bond " << *Binder << "." << endl; 4082 flag = true; 4083 break; 4084 } 4085 } 4086 } 4087 if (flag) { 4088 // create translation vector from their periodically modified distance 4089 for (int i=NDIM;i--;) { 4090 tmp = Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]; 4091 if (fabs(tmp) > BondDistance) 4092 Translationvector.x[i] = (tmp < 0) ? +1. : -1.; 4093 } 4094 Translationvector.MatrixMultiplication(matrix); 4095 //*out << Verbose(3) << "Translation vector is "; 4096 Translationvector.Output(out); 4097 *out << endl; 4098 // apply to all atoms of first component via BFS 4099 for (int i=AtomCount;i--;) 4100 ColorList[i] = white; 4101 AtomStack->Push(Binder->leftatom); 4102 while (!AtomStack->IsEmpty()) { 4103 Walker = AtomStack->PopFirst(); 4104 //*out << Verbose (3) << "Current Walker is: " << *Walker << "." << endl; 4105 ColorList[Walker->nr] = black; // mark as explored 4106 Walker->x.AddVector(&Translationvector); // translate 4107 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through all binding partners 4108 if (ListOfBondsPerAtom[Walker->nr][i] != Binder) { 4109 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 4110 if (ColorList[OtherWalker->nr] == white) { 4111 AtomStack->Push(OtherWalker); // push if yet unexplored 4112 } 4113 } 4114 } 4115 } 4116 // re-add bond 4117 link(Binder, OtherBinder); 4118 } else { 4119 *out << Verbose(3) << "No corrections for this fragment." << endl; 4120 } 4121 //delete(CompStack); 4122 } 4123 4124 // free allocated space from ReturnFullMatrixforSymmetric() 4125 delete(AtomStack); 4126 Free((void **)&ColorList, "molecule::ScanForPeriodicCorrection: *ColorList"); 4127 Free((void **)&matrix, "molecule::ScanForPeriodicCorrection: *matrix"); 4128 *out << Verbose(2) << "End of ScanForPeriodicCorrection." << endl; 4129 4129 }; 4130 4130 … … 4135 4135 double * molecule::ReturnFullMatrixforSymmetric(double *symm) 4136 4136 { 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4137 double *matrix = (double *) Malloc(sizeof(double)*NDIM*NDIM, "molecule::ReturnFullMatrixforSymmetric: *matrix"); 4138 matrix[0] = symm[0]; 4139 matrix[1] = symm[1]; 4140 matrix[2] = symm[3]; 4141 matrix[3] = symm[1]; 4142 matrix[4] = symm[2]; 4143 matrix[5] = symm[4]; 4144 matrix[6] = symm[3]; 4145 matrix[7] = symm[4]; 4146 matrix[8] = symm[5]; 4147 return matrix; 4148 4148 }; 4149 4149 4150 4150 bool KeyCompare::operator() (const KeySet SubgraphA, const KeySet SubgraphB) const 4151 4151 { 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 if ((*IteratorA) <(*IteratorB))4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4152 //cout << "my check is used." << endl; 4153 if (SubgraphA.size() < SubgraphB.size()) { 4154 return true; 4155 } else { 4156 if (SubgraphA.size() > SubgraphB.size()) { 4157 return false; 4158 } else { 4159 KeySet::iterator IteratorA = SubgraphA.begin(); 4160 KeySet::iterator IteratorB = SubgraphB.begin(); 4161 while ((IteratorA != SubgraphA.end()) && (IteratorB != SubgraphB.end())) { 4162 if ((*IteratorA) < (*IteratorB)) 4163 return true; 4164 else if ((*IteratorA) > (*IteratorB)) { 4165 return false; 4166 } // else, go on to next index 4167 IteratorA++; 4168 IteratorB++; 4169 } // end of while loop 4170 }// end of check in case of equal sizes 4171 } 4172 return false; // if we reach this point, they are equal 4173 4173 }; 4174 4174 4175 4175 //bool operator < (KeySet SubgraphA, KeySet SubgraphB) 4176 4176 //{ 4177 // 4177 // return KeyCompare(SubgraphA, SubgraphB); 4178 4178 //}; 4179 4179 … … 4187 4187 inline void InsertFragmentIntoGraph(ofstream *out, struct UniqueFragments *Fragment) 4188 4188 { 4189 4190 4191 testGraphInsert = Fragment->Leaflet->insert(GraphPair (*Fragment->FragmentSet,pair<int,double>(Fragment->FragmentCounter,Fragment->TEFactor)));// store fragment number and current factor4192 4193 4194 4195 4196 4197 ((*(testGraphInsert.first)).second).second += Fragment->TEFactor;// increase the "created" counter4198 4199 4189 GraphTestPair testGraphInsert; 4190 4191 testGraphInsert = Fragment->Leaflet->insert(GraphPair (*Fragment->FragmentSet,pair<int,double>(Fragment->FragmentCounter,Fragment->TEFactor))); // store fragment number and current factor 4192 if (testGraphInsert.second) { 4193 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " successfully inserted." << endl; 4194 Fragment->FragmentCounter++; 4195 } else { 4196 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl; 4197 ((*(testGraphInsert.first)).second).second += Fragment->TEFactor; // increase the "created" counter 4198 *out << Verbose(2) << "New factor is " << ((*(testGraphInsert.first)).second).second << "." << endl; 4199 } 4200 4200 }; 4201 4201 //void inline InsertIntoGraph(ofstream *out, KeyStack &stack, Graph &graph, int *counter, double factor) 4202 4202 //{ 4203 // 4204 // 4205 // 4206 // 4207 // 4203 // // copy stack contents to set and call overloaded function again 4204 // KeySet set; 4205 // for(KeyStack::iterator runner = stack.begin(); runner != stack.begin(); runner++) 4206 // set.insert((*runner)); 4207 // InsertIntoGraph(out, set, graph, counter, factor); 4208 4208 //}; 4209 4209 … … 4216 4216 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter) 4217 4217 { 4218 4219 4220 4221 testGraphInsert = graph1.insert(GraphPair ((*runner).first,pair<int,double>((*counter)++,((*runner).second).second)));// store fragment number and current factor4222 4223 4224 4225 4226 4227 4228 4229 4218 GraphTestPair testGraphInsert; 4219 4220 for(Graph::iterator runner = graph2.begin(); runner != graph2.end(); runner++) { 4221 testGraphInsert = graph1.insert(GraphPair ((*runner).first,pair<int,double>((*counter)++,((*runner).second).second))); // store fragment number and current factor 4222 if (testGraphInsert.second) { 4223 *out << Verbose(2) << "KeySet " << (*counter)-1 << " successfully inserted." << endl; 4224 } else { 4225 *out << Verbose(2) << "KeySet " << (*counter)-1 << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl; 4226 ((*(testGraphInsert.first)).second).second += (*runner).second.second; 4227 *out << Verbose(2) << "New factor is " << (*(testGraphInsert.first)).second.second << "." << endl; 4228 } 4229 } 4230 4230 }; 4231 4231 … … 4234 4234 * -# constructs a complete keyset of the molecule 4235 4235 * -# In a loop over all possible roots from the given rootstack 4236 * 4237 * 4238 * 4236 * -# increases order of root site 4237 * -# calls PowerSetGenerator with this order, the complete keyset and the rootkeynr 4238 * -# for all consecutive lower levels PowerSetGenerator is called with the suborder, the higher order keyset 4239 4239 as the restricted one and each site in the set as the root) 4240 * 4240 * -# these are merged into a fragment list of keysets 4241 4241 * -# All fragment lists (for all orders, i.e. from all destination fields) are merged into one list for return 4242 4242 * Important only is that we create all fragments, it is not important if we create them more than once … … 4250 4250 void molecule::FragmentBOSSANOVA(ofstream *out, Graph *&FragmentList, KeyStack &RootStack, int *MinimumRingSize) 4251 4251 { 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 RootNr = 0;// counts through the roots in RootStack4289 4290 4291 4292 4293 4294 4295 //*out << Verbose(0) << "Bond order " << Walker->GetTrueFather()->AdaptiveOrder << " of Root " << *Walker << " greater than or equal to Minimum Ring size of " << MinimumRingSize << " found is not allowed." << endl;4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 FragmentSearch.BondsPerSPList[2*i] = new bond();// start node4307 FragmentSearch.BondsPerSPList[2*i+1] = new bond();// end node4308 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1];// intertwine these two4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 FragmentLowerOrdersList[RootNr][0] =new Graph;4325 4326 FragmentSearch.Leaflet = FragmentLowerOrdersList[RootNr][0];// set to insertion graph4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 // 4337 // 4338 // 4339 // 4340 // 4341 // 4342 // 4343 // 4344 // 4345 // 4346 // 4347 // 4348 // 4252 Graph ***FragmentLowerOrdersList = NULL; 4253 int NumLevels, NumMolecules, TotalNumMolecules = 0, *NumMoleculesOfOrder = NULL; 4254 int counter = 0, Order; 4255 int UpgradeCount = RootStack.size(); 4256 KeyStack FragmentRootStack; 4257 int RootKeyNr, RootNr; 4258 struct UniqueFragments FragmentSearch; 4259 4260 *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl; 4261 4262 // FragmentLowerOrdersList is a 2D-array of pointer to MoleculeListClass objects, one dimension represents the ANOVA expansion of a single order (i.e. 5) 4263 // with all needed lower orders that are subtracted, the other dimension is the BondOrder (i.e. from 1 to 5) 4264 NumMoleculesOfOrder = (int *) Malloc(sizeof(int)*UpgradeCount, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder"); 4265 FragmentLowerOrdersList = (Graph ***) Malloc(sizeof(Graph **)*UpgradeCount, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); 4266 4267 // initialise the fragments structure 4268 FragmentSearch.ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::PowerSetGenerator: *ShortestPathList"); 4269 FragmentSearch.FragmentCounter = 0; 4270 FragmentSearch.FragmentSet = new KeySet; 4271 FragmentSearch.Root = FindAtom(RootKeyNr); 4272 for (int i=AtomCount;i--;) { 4273 FragmentSearch.ShortestPathList[i] = -1; 4274 } 4275 4276 // Construct the complete KeySet which we need for topmost level only (but for all Roots) 4277 atom *Walker = start; 4278 KeySet CompleteMolecule; 4279 while (Walker->next != end) { 4280 Walker = Walker->next; 4281 CompleteMolecule.insert(Walker->GetTrueFather()->nr); 4282 } 4283 4284 // this can easily be seen: if Order is 5, then the number of levels for each lower order is the total sum of the number of levels above, as 4285 // each has to be split up. E.g. for the second level we have one from 5th, one from 4th, two from 3th (which in turn is one from 5th, one from 4th), 4286 // hence we have overall four 2th order levels for splitting. This also allows for putting all into a single array (FragmentLowerOrdersList[]) 4287 // with the order along the cells as this: 5433222211111111 for BondOrder 5 needing 16=pow(2,5-1) cells (only we use bit-shifting which is faster) 4288 RootNr = 0; // counts through the roots in RootStack 4289 while ((RootNr < UpgradeCount) && (!RootStack.empty())) { 4290 RootKeyNr = RootStack.front(); 4291 RootStack.pop_front(); 4292 Walker = FindAtom(RootKeyNr); 4293 // check cyclic lengths 4294 //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) { 4295 // *out << Verbose(0) << "Bond order " << Walker->GetTrueFather()->AdaptiveOrder << " of Root " << *Walker << " greater than or equal to Minimum Ring size of " << MinimumRingSize << " found is not allowed." << endl; 4296 //} else 4297 { 4298 // increase adaptive order by one 4299 Walker->GetTrueFather()->AdaptiveOrder++; 4300 Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder; 4301 4302 // initialise Order-dependent entries of UniqueFragments structure 4303 FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList"); 4304 FragmentSearch.BondsPerSPCount = (int *) Malloc(sizeof(int)*Order, "molecule::PowerSetGenerator: *BondsPerSPCount"); 4305 for (int i=Order;i--;) { 4306 FragmentSearch.BondsPerSPList[2*i] = new bond(); // start node 4307 FragmentSearch.BondsPerSPList[2*i+1] = new bond(); // end node 4308 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1]; // intertwine these two 4309 FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i]; 4310 FragmentSearch.BondsPerSPCount[i] = 0; 4311 } 4312 4313 // allocate memory for all lower level orders in this 1D-array of ptrs 4314 NumLevels = 1 << (Order-1); // (int)pow(2,Order); 4315 FragmentLowerOrdersList[RootNr] = (Graph **) Malloc(sizeof(Graph *)*NumLevels, "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]"); 4316 for (int i=0;i<NumLevels;i++) 4317 FragmentLowerOrdersList[RootNr][i] = NULL; 4318 4319 // create top order where nothing is reduced 4320 *out << Verbose(0) << "==============================================================================================================" << endl; 4321 *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << " 4322 4323 // Create list of Graphs of current Bond Order (i.e. F_{ij}) 4324 FragmentLowerOrdersList[RootNr][0] = new Graph; 4325 FragmentSearch.TEFactor = 1.; 4326 FragmentSearch.Leaflet = FragmentLowerOrdersList[RootNr][0]; // set to insertion graph 4327 FragmentSearch.Root = Walker; 4328 NumMoleculesOfOrder[RootNr] = PowerSetGenerator(out, Walker->AdaptiveOrder, FragmentSearch, CompleteMolecule); 4329 *out << Verbose(1) << "Number of resulting KeySets is: " << NumMoleculesOfOrder[RootNr] << "." << endl; 4330 if (NumMoleculesOfOrder[RootNr] != 0) { 4331 NumMolecules = 0; 4332 4333 // we don't have to dive into suborders! These keysets are all already created on lower orders! 4334 // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed) 4335 4336 // if ((NumLevels >> 1) > 0) { 4337 // // create lower order fragments 4338 // *out << Verbose(0) << "Creating list of unique fragments of lower Bond Order terms to be subtracted." << endl; 4339 // Order = Walker->AdaptiveOrder; 4340 // for (int source=0;source<(NumLevels >> 1);source++) { // 1-terms don't need any more splitting, that's why only half is gone through (shift again) 4341 // // step down to next order at (virtual) boundary of powers of 2 in array 4342 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order)) 4343 // Order--; 4344 // *out << Verbose(0) << "Current Order is: " << Order << "." << endl; 4345 // for (int SubOrder=Order-1;SubOrder>0;SubOrder--) { 4346 // int dest = source + (1 << (Walker->AdaptiveOrder-(SubOrder+1))); 4347 // *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl; 4348 // *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl; 4349 4349 // 4350 // 4351 // 4352 // 4353 // 4354 // 4355 // 4356 // 4357 // 4358 // FragmentSearch.Leaflet = &TempFragmentList;// set to insertion graph4359 // 4360 // 4361 // 4362 // 4363 // 4364 // 4365 // 4366 // 4367 // 4368 // 4369 // 4370 4371 4372 // 4373 4374 4375 4376 4377 // 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4350 // // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules 4351 // //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl; 4352 // //NumMolecules = 0; 4353 // FragmentLowerOrdersList[RootNr][dest] = new Graph; 4354 // for(Graph::iterator runner = (*FragmentLowerOrdersList[RootNr][source]).begin();runner != (*FragmentLowerOrdersList[RootNr][source]).end(); runner++) { 4355 // for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 4356 // Graph TempFragmentList; 4357 // FragmentSearch.TEFactor = -(*runner).second.second; 4358 // FragmentSearch.Leaflet = &TempFragmentList; // set to insertion graph 4359 // FragmentSearch.Root = FindAtom(*sprinter); 4360 // NumMoleculesOfOrder[RootNr] += PowerSetGenerator(out, SubOrder, FragmentSearch, (*runner).first); 4361 // // insert new keysets FragmentList into FragmentLowerOrdersList[Walker->AdaptiveOrder-1][dest] 4362 // *out << Verbose(1) << "Merging resulting key sets with those present in destination " << dest << "." << endl; 4363 // InsertGraphIntoGraph(out, *FragmentLowerOrdersList[RootNr][dest], TempFragmentList, &NumMolecules); 4364 // } 4365 // } 4366 // *out << Verbose(1) << "Number of resulting molecules for SubOrder " << SubOrder << " is: " << NumMolecules << "." << endl; 4367 // } 4368 // } 4369 // } 4370 } else { 4371 Walker->GetTrueFather()->MaxOrder = true; 4372 // *out << Verbose(1) << "Hence, we don't dive into SubOrders ... " << endl; 4373 } 4374 // now, we have completely filled each cell of FragmentLowerOrdersList[] for the current Walker->AdaptiveOrder 4375 //NumMoleculesOfOrder[Walker->AdaptiveOrder-1] = NumMolecules; 4376 TotalNumMolecules += NumMoleculesOfOrder[RootNr]; 4377 // *out << Verbose(1) << "Number of resulting molecules for Order " << (int)Walker->GetTrueFather()->AdaptiveOrder << " is: " << NumMoleculesOfOrder[RootNr] << "." << endl; 4378 RootStack.push_back(RootKeyNr); // put back on stack 4379 RootNr++; 4380 4381 // free Order-dependent entries of UniqueFragments structure for next loop cycle 4382 Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount"); 4383 for (int i=Order;i--;) { 4384 delete(FragmentSearch.BondsPerSPList[2*i]); 4385 delete(FragmentSearch.BondsPerSPList[2*i+1]); 4386 } 4387 Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList"); 4388 } 4389 } 4390 *out << Verbose(0) << "==============================================================================================================" << endl; 4391 *out << Verbose(1) << "Total number of resulting molecules is: " << TotalNumMolecules << "." << endl; 4392 *out << Verbose(0) << "==============================================================================================================" << endl; 4393 4394 // cleanup FragmentSearch structure 4395 Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList"); 4396 delete(FragmentSearch.FragmentSet); 4397 4398 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein) 4399 // 5433222211111111 4400 // 43221111 4401 // 3211 4402 // 21 4403 // 1 4404 4405 // Subsequently, we combine all into a single list (FragmentList) 4406 4407 *out << Verbose(0) << "Combining the lists of all orders per order and finally into a single one." << endl; 4408 if (FragmentList == NULL) { 4409 FragmentList = new Graph; 4410 counter = 0; 4411 } else { 4412 counter = FragmentList->size(); 4413 } 4414 RootNr = 0; 4415 while (!RootStack.empty()) { 4416 RootKeyNr = RootStack.front(); 4417 RootStack.pop_front(); 4418 Walker = FindAtom(RootKeyNr); 4419 NumLevels = 1 << (Walker->AdaptiveOrder - 1); 4420 for(int i=0;i<NumLevels;i++) { 4421 if (FragmentLowerOrdersList[RootNr][i] != NULL) { 4422 InsertGraphIntoGraph(out, *FragmentList, (*FragmentLowerOrdersList[RootNr][i]), &counter); 4423 delete(FragmentLowerOrdersList[RootNr][i]); 4424 } 4425 } 4426 Free((void **)&FragmentLowerOrdersList[RootNr], "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]"); 4427 RootNr++; 4428 } 4429 Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); 4430 Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder"); 4431 4432 *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl; 4433 4433 }; 4434 4434 … … 4440 4440 inline int CompareDoubles (const void * a, const void * b) 4441 4441 { 4442 4443 4444 4445 4446 4447 4442 if (*(double *)a > *(double *)b) 4443 return -1; 4444 else if (*(double *)a < *(double *)b) 4445 return 1; 4446 else 4447 return 0; 4448 4448 }; 4449 4449 … … 4456 4456 int * molecule::IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold) 4457 4457 { 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 //*out << Verbose(5) << "Element " <<flag << ": " << ElementsInMolecule[flag] << " <-> " << OtherMolecule->ElementsInMolecule[flag] << "." << endl;4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 *out << Verbose(5) << "Distances squared: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " <<threshold << endl;4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4458 int flag; 4459 double *Distances = NULL, *OtherDistances = NULL; 4460 Vector CenterOfGravity, OtherCenterOfGravity; 4461 size_t *PermMap = NULL, *OtherPermMap = NULL; 4462 int *PermutationMap = NULL; 4463 atom *Walker = NULL; 4464 bool result = true; // status of comparison 4465 4466 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 4467 /// first count both their atoms and elements and update lists thereby ... 4468 //*out << Verbose(0) << "Counting atoms, updating list" << endl; 4469 CountAtoms(out); 4470 OtherMolecule->CountAtoms(out); 4471 CountElements(); 4472 OtherMolecule->CountElements(); 4473 4474 /// ... and compare: 4475 /// -# AtomCount 4476 if (result) { 4477 if (AtomCount != OtherMolecule->AtomCount) { 4478 *out << Verbose(4) << "AtomCounts don't match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl; 4479 result = false; 4480 } else *out << Verbose(4) << "AtomCounts match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl; 4481 } 4482 /// -# ElementCount 4483 if (result) { 4484 if (ElementCount != OtherMolecule->ElementCount) { 4485 *out << Verbose(4) << "ElementCount don't match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl; 4486 result = false; 4487 } else *out << Verbose(4) << "ElementCount match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl; 4488 } 4489 /// -# ElementsInMolecule 4490 if (result) { 4491 for (flag=MAX_ELEMENTS;flag--;) { 4492 //*out << Verbose(5) << "Element " << flag << ": " << ElementsInMolecule[flag] << " <-> " << OtherMolecule->ElementsInMolecule[flag] << "." << endl; 4493 if (ElementsInMolecule[flag] != OtherMolecule->ElementsInMolecule[flag]) 4494 break; 4495 } 4496 if (flag < MAX_ELEMENTS) { 4497 *out << Verbose(4) << "ElementsInMolecule don't match." << endl; 4498 result = false; 4499 } else *out << Verbose(4) << "ElementsInMolecule match." << endl; 4500 } 4501 /// then determine and compare center of gravity for each molecule ... 4502 if (result) { 4503 *out << Verbose(5) << "Calculating Centers of Gravity" << endl; 4504 DeterminePeriodicCenter(CenterOfGravity); 4505 OtherMolecule->DeterminePeriodicCenter(OtherCenterOfGravity); 4506 *out << Verbose(5) << "Center of Gravity: "; 4507 CenterOfGravity.Output(out); 4508 *out << endl << Verbose(5) << "Other Center of Gravity: "; 4509 OtherCenterOfGravity.Output(out); 4510 *out << endl; 4511 if (CenterOfGravity.DistanceSquared(&OtherCenterOfGravity) > threshold*threshold) { 4512 *out << Verbose(4) << "Centers of gravity don't match." << endl; 4513 result = false; 4514 } 4515 } 4516 4517 /// ... then make a list with the euclidian distance to this center for each atom of both molecules 4518 if (result) { 4519 *out << Verbose(5) << "Calculating distances" << endl; 4520 Distances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: Distances"); 4521 OtherDistances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: OtherDistances"); 4522 Walker = start; 4523 while (Walker->next != end) { 4524 Walker = Walker->next; 4525 Distances[Walker->nr] = CenterOfGravity.DistanceSquared(&Walker->x); 4526 } 4527 Walker = OtherMolecule->start; 4528 while (Walker->next != OtherMolecule->end) { 4529 Walker = Walker->next; 4530 OtherDistances[Walker->nr] = OtherCenterOfGravity.DistanceSquared(&Walker->x); 4531 } 4532 4533 /// ... sort each list (using heapsort (o(N log N)) from GSL) 4534 *out << Verbose(5) << "Sorting distances" << endl; 4535 PermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermMap"); 4536 OtherPermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *OtherPermMap"); 4537 gsl_heapsort_index (PermMap, Distances, AtomCount, sizeof(double), CompareDoubles); 4538 gsl_heapsort_index (OtherPermMap, OtherDistances, AtomCount, sizeof(double), CompareDoubles); 4539 PermutationMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermutationMap"); 4540 *out << Verbose(5) << "Combining Permutation Maps" << endl; 4541 for(int i=AtomCount;i--;) 4542 PermutationMap[PermMap[i]] = (int) OtherPermMap[i]; 4543 4544 /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all 4545 *out << Verbose(4) << "Comparing distances" << endl; 4546 flag = 0; 4547 for (int i=0;i<AtomCount;i++) { 4548 *out << Verbose(5) << "Distances squared: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " << threshold << endl; 4549 if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) > threshold*threshold) 4550 flag = 1; 4551 } 4552 Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap"); 4553 Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap"); 4554 4555 /// free memory 4556 Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances"); 4557 Free((void **)&OtherDistances, "molecule::IsEqualToWithinThreshold: OtherDistances"); 4558 if (flag) { // if not equal 4559 Free((void **)&PermutationMap, "molecule::IsEqualToWithinThreshold: *PermutationMap"); 4560 result = false; 4561 } 4562 } 4563 /// return pointer to map if all distances were below \a threshold 4564 *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl; 4565 if (result) { 4566 *out << Verbose(3) << "Result: Equal." << endl; 4567 return PermutationMap; 4568 } else { 4569 *out << Verbose(3) << "Result: Not equal." << endl; 4570 return NULL; 4571 } 4572 4572 }; 4573 4573 … … 4581 4581 int * molecule::GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule) 4582 4582 { 4583 4584 4585 int *AtomicMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::GetAtomicMap: *AtomicMap");//Calloc4586 4587 4588 if (OtherMolecule == this) {// same molecule4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4583 atom *Walker = NULL, *OtherWalker = NULL; 4584 *out << Verbose(3) << "Begin of GetFatherAtomicMap." << endl; 4585 int *AtomicMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::GetAtomicMap: *AtomicMap"); //Calloc 4586 for (int i=AtomCount;i--;) 4587 AtomicMap[i] = -1; 4588 if (OtherMolecule == this) { // same molecule 4589 for (int i=AtomCount;i--;) // no need as -1 means already that there is trivial correspondence 4590 AtomicMap[i] = i; 4591 *out << Verbose(4) << "Map is trivial." << endl; 4592 } else { 4593 *out << Verbose(4) << "Map is "; 4594 Walker = start; 4595 while (Walker->next != end) { 4596 Walker = Walker->next; 4597 if (Walker->father == NULL) { 4598 AtomicMap[Walker->nr] = -2; 4599 } else { 4600 OtherWalker = OtherMolecule->start; 4601 while (OtherWalker->next != OtherMolecule->end) { 4602 OtherWalker = OtherWalker->next; 4603 //for (int i=0;i<AtomCount;i++) { // search atom 4604 //for (int j=0;j<OtherMolecule->AtomCount;j++) { 4605 //*out << Verbose(4) << "Comparing father " << Walker->father << " with the other one " << OtherWalker->father << "." << endl; 4606 if (Walker->father == OtherWalker) 4607 AtomicMap[Walker->nr] = OtherWalker->nr; 4608 } 4609 } 4610 *out << AtomicMap[Walker->nr] << "\t"; 4611 } 4612 *out << endl; 4613 } 4614 *out << Verbose(3) << "End of GetFatherAtomicMap." << endl; 4615 return AtomicMap; 4616 4616 }; 4617 4617 … … 4627 4627 bool molecule::OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output) 4628 4628 { 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 }; 4629 double temperature; 4630 atom *Walker = NULL; 4631 // test stream 4632 if (output == NULL) 4633 return false; 4634 else 4635 *output << "# Step Temperature [K] Temperature [a.u.]" << endl; 4636 for (int step=startstep;step < endstep; step++) { // loop over all time steps 4637 temperature = 0.; 4638 Walker = start; 4639 while (Walker->next != end) { 4640 Walker = Walker->next; 4641 for (int i=NDIM;i--;) 4642 temperature += Walker->type->mass * Trajectories[Walker].U.at(step).x[i]* Trajectories[Walker].U.at(step).x[i]; 4643 } 4644 *output << step << "\t" << temperature*AtomicEnergyToKelvin << "\t" << temperature << endl; 4645 } 4646 return true; 4647 }; -
src/molecules.hpp
r178f92 r437922 76 76 struct KeyCompare 77 77 { 78 78 bool operator() (const KeySet SubgraphA, const KeySet SubgraphB) const; 79 79 }; 80 80 81 81 struct Trajectory 82 82 { 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); 83 vector<Vector> R; //!< position vector 84 vector<Vector> U; //!< velocity vector 85 vector<Vector> F; //!< last force vector 86 atom *ptr; //!< pointer to atom whose trajectory we contain 87 }; 88 89 //bool operator < (KeySet SubgraphA, KeySet SubgraphB); //note: this declaration is important, otherwise normal < is used (producing wrong order) 90 90 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); 91 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter); // Insert all KeySet's in a Graph into another Graph 92 92 int CompareDoubles (const void * a, const void * b); 93 93 … … 97 97 98 98 // 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)) 99 #define RDET3(a) ((a)[0]*(a)[4]*(a)[8] + (a)[3]*(a)[7]*(a)[2] + (a)[6]*(a)[1]*(a)[5] - (a)[2]*(a)[4]*(a)[6] - (a)[5]*(a)[7]*(a)[0] - (a)[8]*(a)[1]*(a)[3]) //!< hard-coded determinant of a 3x3 matrix 100 #define RDET2(a0,a1,a2,a3) ((a0)*(a3)-(a1)*(a2)) //!< hard-coded determinant of a 2x2 matrix 101 101 102 102 … … 104 104 */ 105 105 struct LSQ_params { 106 107 106 Vector **vectors; 107 int num; 108 108 }; 109 109 … … 113 113 */ 114 114 struct lsq_params { 115 116 117 115 gsl_vector *x; 116 const molecule *mol; 117 element *type; 118 118 }; 119 119 … … 122 122 */ 123 123 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 124 public: 125 Vector x; //!< coordinate array of atom, giving position within cell 126 Vector v; //!< velocity array of atom 127 element *type; //!< pointing to element 128 atom *previous; //!< previous atom in molecule list 129 atom *next; //!< next atom in molecule list 130 atom *father; //!< In many-body bond order fragmentations points to originating atom 131 atom *Ancestor; //!< "Father" in Depth-First-Search 132 char *Name; //!< unique name used during many-body bond-order fragmentation 133 int FixedIon; //!< config variable that states whether forces act on the ion or not 134 int *sort; //!< sort criteria 135 int nr; //!< continuous, unique number 136 int GraphNr; //!< unique number, given in DepthFirstSearchAnalysis() 137 int *ComponentNr;//!< belongs to this nonseparable components, given in DepthFirstSearchAnalysis() (if more than one, then is SeparationVertex) 138 int LowpointNr; //!< needed in DepthFirstSearchAnalysis() to detect nonseparable components, is the lowest possible number of an atom to reach via tree edges only followed by at most one back edge. 139 bool SeparationVertex; //!< whether this atom separates off subsets of atoms or not, determined in DepthFirstSearchAnalysis() 140 bool IsCyclic; //!< whether atom belong to as cycle or not, determined in DepthFirstSearchAnalysis() 141 unsigned char AdaptiveOrder; //!< current present bond order at site (0 means "not set") 142 bool MaxOrder; //!< whether this atom as a root in fragmentation still creates more fragments on higher orders or not 143 144 atom(); 145 ~atom(); 146 147 bool Output(int ElementNo, int AtomNo, ofstream *out, const char *comment = NULL) const; 148 bool OutputXYZLine(ofstream *out) const; 149 atom *GetTrueFather(); 150 bool Compare(atom &ptr); 151 152 private: 153 153 }; 154 154 … … 161 161 */ 162 162 class bond { 163 164 atom *leftatom;//!< first bond partner165 atom *rightatom;//!< second bond partner166 167 bond *next;//!< next atom in molecule list168 int HydrogenBond;//!< Number of hydrogen atoms in the bond169 int BondDegree;//!< single, double, triple, ... bond170 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 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 enum Shading Used;//!< marker in depth-first search, DepthFirstSearchAnalysis()163 public: 164 atom *leftatom; //!< first bond partner 165 atom *rightatom; //!< second bond partner 166 bond *previous; //!< previous atom in molecule list 167 bond *next; //!< next atom in molecule list 168 int HydrogenBond; //!< Number of hydrogen atoms in the bond 169 int BondDegree; //!< single, double, triple, ... bond 170 int nr; //!< unique number in a molecule, updated by molecule::CreateAdjacencyList() 171 bool Cyclic; //!< flag whether bond is part of a cycle or not, given in DepthFirstSearchAnalysis() 172 enum EdgeType Type;//!< whether this is a tree or back edge 173 174 atom * GetOtherAtom(atom *Atom) const; 175 bond * GetFirstBond(); 176 bond * GetLastBond(); 177 178 bool MarkUsed(enum Shading color); 179 enum Shading IsUsed(); 180 void ResetUsed(); 181 bool Contains(const atom *ptr); 182 bool Contains(const int nr); 183 184 bond(); 185 bond(atom *left, atom *right); 186 bond(atom *left, atom *right, int degree); 187 bond(atom *left, atom *right, int degree, int number); 188 ~bond(); 189 190 private: 191 enum Shading Used; //!< marker in depth-first search, DepthFirstSearchAnalysis() 192 192 }; 193 193 … … 200 200 */ 201 201 class molecule { 202 203 204 205 atom *start;//!< start of atom list206 atom *end;//!< end of atom list207 bond *first;//!< start of bond list208 bond *last;//!< end of bond list209 210 211 int MDSteps;//!< The number of MD steps in Trajectories212 int *NumberOfBondsPerAtom;//!< Number of Bonds each atom has213 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 therein216 217 int NoNonHydrogen;//!< number of non-hydrogen atoms in molecule218 int NoNonBonds;//!< number of non-hydrogen bonds in molecule219 int NoCyclicBonds;//!< number of cyclic bonds in molecule, by DepthFirstSearchAnalysis()220 double BondDistance;//!< typical bond distance used in CreateAdjacencyList() and furtheron221 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 int last_atom;//!< number given to last atom202 public: 203 double cell_size[6];//!< cell size 204 periodentafel *elemente; //!< periodic table with each element 205 atom *start; //!< start of atom list 206 atom *end; //!< end of atom list 207 bond *first; //!< start of bond list 208 bond *last; //!< end of bond list 209 bond ***ListOfBondsPerAtom; //!< pointer list for each atom and each bond it has 210 map<atom *, struct Trajectory> Trajectories; //!< contains old trajectory points 211 int MDSteps; //!< The number of MD steps in Trajectories 212 int *NumberOfBondsPerAtom; //!< Number of Bonds each atom has 213 int AtomCount; //!< number of atoms, brought up-to-date by CountAtoms() 214 int BondCount; //!< number of atoms, brought up-to-date by CountBonds() 215 int ElementCount; //!< how many unique elements are therein 216 int ElementsInMolecule[MAX_ELEMENTS]; //!< list whether element (sorted by atomic number) is alread present or not 217 int NoNonHydrogen; //!< number of non-hydrogen atoms in molecule 218 int NoNonBonds; //!< number of non-hydrogen bonds in molecule 219 int NoCyclicBonds; //!< number of cyclic bonds in molecule, by DepthFirstSearchAnalysis() 220 double BondDistance; //!< typical bond distance used in CreateAdjacencyList() and furtheron 221 bool ActiveFlag; //!< in a MoleculeListClass used to discern active from inactive molecules 222 Vector Center; //!< Center of molecule in a global box 223 char name[MAXSTRINGSIZE]; //!< arbitrary name 224 int IndexNr; //!< index of molecule in a MoleculeListClass 225 226 molecule(periodentafel *teil); 227 ~molecule(); 228 229 /// remove atoms from molecule. 230 bool AddAtom(atom *pointer); 231 bool RemoveAtom(atom *pointer); 232 bool UnlinkAtom(atom *pointer); 233 bool CleanupMolecule(); 234 235 /// Add/remove atoms to/from molecule. 236 atom * AddCopyAtom(atom *pointer); 237 bool AddXYZFile(string filename); 238 bool AddHydrogenReplacementAtom(ofstream *out, bond *Bond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem); 239 bond * AddBond(atom *first, atom *second, int degree); 240 bool RemoveBond(bond *pointer); 241 bool RemoveBonds(atom *BondPartner); 242 243 /// Find atoms. 244 atom * FindAtom(int Nr) const; 245 atom * AskAtom(string text); 246 247 /// Count and change present atoms' coordination. 248 void CountAtoms(ofstream *out); 249 void CountElements(); 250 void CalculateOrbitals(class config &configuration); 251 bool CenterInBox(ofstream *out, Vector *BoxLengths); 252 void CenterEdge(ofstream *out, Vector *max); 253 void CenterOrigin(ofstream *out); 254 void CenterPeriodic(ofstream *out); 255 void CenterAtVector(ofstream *out, Vector *newcenter); 256 void Translate(const Vector *x); 257 void Mirror(const Vector *x); 258 void Align(Vector *n); 259 void Scale(double **factor); 260 void DeterminePeriodicCenter(Vector ¢er); 261 Vector * DetermineCenterOfGravity(ofstream *out); 262 Vector * DetermineCenterOfAll(ofstream *out); 263 void SetNameFromFilename(const char *filename); 264 void SetBoxDimension(Vector *dim); 265 double * ReturnFullMatrixforSymmetric(double *cell_size); 266 void ScanForPeriodicCorrection(ofstream *out); 267 void PrincipalAxisSystem(ofstream *out, bool DoRotate); 268 double VolumeOfConvexEnvelope(ofstream *out, bool IsAngstroem); 269 Vector* FindEmbeddingHole(ofstream *out, molecule *srcmol); 270 271 bool VerletForceIntegration(char *file, double delta_t, bool IsAngstroem); 272 273 bool CheckBounds(const Vector *x) const; 274 void GetAlignvector(struct lsq_params * par) const; 275 276 /// Initialising routines in fragmentation 277 void CreateAdjacencyList2(ofstream *out, ifstream *output); 278 void CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem); 279 void CreateListOfBondsPerAtom(ofstream *out); 280 281 // Graph analysis 282 MoleculeLeafClass * DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack); 283 void CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> *BackEdgeStack, int *&MinimumRingSize); 284 bool PickLocalBackEdges(ofstream *out, atom **ListOfLocalAtoms, class StackClass<bond *> *&ReferenceStack, class StackClass<bond *> *&LocalStack); 285 bond * FindNextUnused(atom *vertex); 286 void SetNextComponentNumber(atom *vertex, int nr); 287 void InitComponentNumbers(); 288 void OutputComponentNumber(ofstream *out, atom *vertex); 289 void ResetAllBondsToUnused(); 290 void ResetAllAtomNumbers(); 291 int CountCyclicBonds(ofstream *out); 292 bool CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment); 293 string GetColor(enum Shading color); 294 295 molecule *CopyMolecule(); 296 297 /// Fragment molecule by two different approaches: 298 int FragmentMolecule(ofstream *out, int Order, config *configuration); 299 bool CheckOrderAtSite(ofstream *out, bool *AtomMask, Graph *GlobalKeySetList, int Order, int *MinimumRingSize, char *path = NULL); 300 bool StoreAdjacencyToFile(ofstream *out, char *path); 301 bool CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms); 302 bool ParseOrderAtSiteFromFile(ofstream *out, char *path); 303 bool StoreOrderAtSiteFile(ofstream *out, char *path); 304 bool ParseKeySetFile(ofstream *out, char *filename, Graph *&FragmentList); 305 bool StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path); 306 bool StoreForcesFile(ofstream *out, MoleculeListClass *BondFragments, char *path, int *SortIndex); 307 bool CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex); 308 bool ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet); 309 void BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem); 310 /// -# BOSSANOVA 311 void FragmentBOSSANOVA(ofstream *out, Graph *&FragmentList, KeyStack &RootStack, int *MinimumRingSize); 312 int PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet); 313 bool BuildInducedSubgraph(ofstream *out, const molecule *Father); 314 molecule * StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem); 315 void SPFragmentGenerator(ofstream *out, struct UniqueFragments *FragmentSearch, int RootDistance, bond **BondsSet, int SetDimension, int SubOrder); 316 int LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList); 317 int GuesstimateFragmentCount(ofstream *out, int order); 318 319 // Recognize doubly appearing molecules in a list of them 320 int * IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold); 321 int * GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule); 322 323 // Output routines. 324 bool Output(ofstream *out); 325 bool OutputTrajectories(ofstream *out); 326 void OutputListOfBonds(ofstream *out) const; 327 bool OutputXYZ(ofstream *out) const; 328 bool OutputTrajectoriesXYZ(ofstream *out); 329 bool Checkout(ofstream *out) const; 330 bool OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output); 331 332 private: 333 int last_atom; //!< number given to last atom 334 334 }; 335 335 … … 337 337 */ 338 338 class MoleculeListClass { 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 339 public: 340 MoleculeList ListOfMolecules; //!< List of the contained molecules 341 int MaxIndex; 342 343 MoleculeListClass(); 344 ~MoleculeListClass(); 345 346 bool AddHydrogenCorrection(ofstream *out, char *path); 347 bool StoreForcesFile(ofstream *out, char *path, int *SortIndex); 348 void insert(molecule *mol); 349 molecule * ReturnIndex(int index); 350 bool OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex); 351 int NumberOfActiveMolecules(); 352 void Enumerate(ofstream *out); 353 void Output(ofstream *out); 354 355 // merging of molecules 356 356 bool SimpleMerge(molecule *mol, molecule *srcmol); 357 357 bool SimpleAdd(molecule *mol, molecule *srcmol); … … 361 361 bool EmbedMerge(molecule *mol, molecule *srcmol); 362 362 363 363 private: 364 364 }; 365 365 … … 369 369 */ 370 370 class MoleculeLeafClass { 371 372 molecule *Leaf;//!< molecule of this leaf373 //MoleculeLeafClass *UpLeaf;//!< Leaf one level up374 //MoleculeLeafClass *DownLeaf;//!< First leaf one level down375 MoleculeLeafClass *previous;//!< Previous leaf on this level376 MoleculeLeafClass *next;//!< Next leaf on this level377 378 379 380 381 382 383 384 385 386 387 388 371 public: 372 molecule *Leaf; //!< molecule of this leaf 373 //MoleculeLeafClass *UpLeaf; //!< Leaf one level up 374 //MoleculeLeafClass *DownLeaf; //!< First leaf one level down 375 MoleculeLeafClass *previous; //!< Previous leaf on this level 376 MoleculeLeafClass *next; //!< Next leaf on this level 377 378 //MoleculeLeafClass(MoleculeLeafClass *Up, MoleculeLeafClass *Previous); 379 MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf); 380 ~MoleculeLeafClass(); 381 382 bool AddLeaf(molecule *ptr, MoleculeLeafClass *Previous); 383 bool FillBondStructureFromReference(ofstream *out, molecule *reference, int &FragmentCounter, atom ***&ListOfLocalAtoms, bool FreeList = false); 384 bool FillRootStackForSubgraphs(ofstream *out, KeyStack *&RootStack, bool *AtomMask, int &FragmentCounter); 385 bool AssignKeySetsToFragment(ofstream *out, molecule *reference, Graph *KeySetList, atom ***&ListOfLocalAtoms, Graph **&FragmentList, int &FragmentCounter, bool FreeList = false); 386 bool FillListOfLocalAtoms(ofstream *out, atom ***&ListOfLocalAtoms, const int FragmentCounter, const int GlobalAtomCount, bool &FreeList); 387 void TranslateIndicesToGlobalIDs(ofstream *out, Graph **FragmentList, int &FragmentCounter, int &TotalNumberOfKeySets, Graph &TotalGraph); 388 int Count() const; 389 389 }; 390 390 … … 393 393 */ 394 394 class config { 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 395 public: 396 int PsiType; 397 int MaxPsiDouble; 398 int PsiMaxNoUp; 399 int PsiMaxNoDown; 400 int MaxMinStopStep; 401 int InitMaxMinStopStep; 402 int ProcPEGamma; 403 int ProcPEPsi; 404 char *configpath; 405 char *configname; 406 bool FastParsing; 407 double Deltat; 408 string basis; 409 410 private: 411 char *mainname; 412 char *defaultpath; 413 char *pseudopotpath; 414 415 int DoOutVis; 416 int DoOutMes; 417 int DoOutNICS; 418 int DoOutOrbitals; 419 int DoOutCurrent; 420 int DoFullCurrent; 421 int DoPerturbation; 422 int DoWannier; 423 int CommonWannier; 424 double SawtoothStart; 425 int VectorPlane; 426 double VectorCut; 427 int UseAddGramSch; 428 int Seed; 429 430 int MaxOuterStep; 431 int OutVisStep; 432 int OutSrcStep; 433 double TargetTemp; 434 int ScaleTempStep; 435 int MaxPsiStep; 436 double EpsWannier; 437 438 int MaxMinStep; 439 double RelEpsTotalEnergy; 440 double RelEpsKineticEnergy; 441 int MaxMinGapStopStep; 442 int MaxInitMinStep; 443 double InitRelEpsTotalEnergy; 444 double InitRelEpsKineticEnergy; 445 int InitMaxMinGapStopStep; 446 447 //double BoxLength[NDIM*NDIM]; 448 449 double ECut; 450 int MaxLevel; 451 int RiemannTensor; 452 int LevRFactor; 453 int RiemannLevel; 454 int Lev0Factor; 455 int RTActualUse; 456 int AddPsis; 457 458 double RCut; 459 int StructOpt; 460 int IsAngstroem; 461 int RelativeCoord; 462 int MaxTypes; 463 464 465 int ParseForParameter(int verbose, ifstream *file, const char *name, int sequential, int const xth, int const yth, int type, void *value, int repetition, int critical); 466 467 public: 468 config(); 469 ~config(); 470 471 int TestSyntax(char *filename, periodentafel *periode, molecule *mol); 472 void Load(char *filename, periodentafel *periode, molecule *mol); 473 void LoadOld(char *filename, periodentafel *periode, molecule *mol); 474 void RetrieveConfigPathAndName(string filename); 475 bool Save(const char *filename, periodentafel *periode, molecule *mol) const; 476 bool SaveMPQC(const char *filename, molecule *mol) const; 477 void Edit(); 478 bool GetIsAngstroem() const; 479 char *GetDefaultPath() const; 480 void SetDefaultPath(const char *path); 481 481 }; 482 482 -
src/parser.cpp
r178f92 r437922 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 58 59 60 61 62 63 64 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; 65 65 }; 66 66 … … 68 68 */ 69 69 MatrixContainer::~MatrixContainer() { 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 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 93 }; 94 94 95 95 96 96 /** Parsing a number of matrices. 97 * 98 * 99 * 100 * 101 * 102 * 97 * -# open the matrix file 98 * -# skip some lines (\a skiplines) 99 * -# scan header lines for number of columns 100 * -# scan lines for number of rows 101 * -# allocate matrix 102 * -# loop over found column and row counts and parse in each entry 103 103 * \param *name directory with files 104 104 * \param skiplines number of inital lines to skip … … 109 109 bool MatrixContainer::ParseMatrix(const char *name, int skiplines, int skipcolumns, int MatrixNr) 110 110 { 111 112 113 114 115 116 117 //cout << "Opening " << name << " ... "<< input << endl;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 RowCounter[MatrixNr]=-1;// counts one line too much144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 input.getline(Header, 1023);// skip header165 166 for(int k=skipcolumns;k--;)// skip columns in header too167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 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; 190 190 }; 191 191 … … 193 193 * -# First, count the number of matrices by counting lines in KEYSETFILE 194 194 * -# Then, 195 * 196 * 197 * 198 * 199 * 200 * 201 * 195 * -# construct the fragment number 196 * -# open the matrix file 197 * -# skip some lines (\a skiplines) 198 * -# scan header lines for number of columns 199 * -# scan lines for number of rows 200 * -# allocate matrix 201 * -# loop over found column and row counts and parse in each entry 202 202 * -# Finally, allocate one additional matrix (\a MatrixCounter) containing combined or temporary values 203 203 * \param *name directory with files … … 210 210 bool MatrixContainer::ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns) 211 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 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; 251 251 }; 252 252 … … 260 260 bool MatrixContainer::AllocateMatrix(char *GivenHeader, int MCounter, int *RCounter, int CCounter) 261 261 { 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 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; 279 279 }; 280 280 … … 284 284 bool MatrixContainer::ResetMatrix() 285 285 { 286 287 288 289 290 286 for(int i=MatrixCounter+1;i--;) 287 for(int j=RowCounter[i]+1;j--;) 288 for(int k=ColumnCounter;k--;) 289 Matrix[i][j][k] = 0.; 290 return true; 291 291 }; 292 292 … … 296 296 double MatrixContainer::FindMaxValue() 297 297 { 298 299 300 301 302 303 304 305 298 double max = Matrix[0][0][0]; 299 for(int i=MatrixCounter+1;i--;) 300 for(int j=RowCounter[i]+1;j--;) 301 for(int k=ColumnCounter;k--;) 302 if (fabs(Matrix[i][j][k]) > max) 303 max = fabs(Matrix[i][j][k]); 304 if (fabs(max) < MYEPSILON) 305 max += MYEPSILON; 306 306 return max; 307 307 }; … … 312 312 double MatrixContainer::FindMinValue() 313 313 { 314 315 316 317 318 319 320 321 322 314 double min = Matrix[0][0][0]; 315 for(int i=MatrixCounter+1;i--;) 316 for(int j=RowCounter[i]+1;j--;) 317 for(int k=ColumnCounter;k--;) 318 if (fabs(Matrix[i][j][k]) < min) 319 min = fabs(Matrix[i][j][k]); 320 if (fabs(min) < MYEPSILON) 321 min += MYEPSILON; 322 return min; 323 323 }; 324 324 … … 330 330 bool MatrixContainer::SetLastMatrix(double value, int skipcolumns) 331 331 { 332 333 334 335 332 for(int j=RowCounter[MatrixCounter]+1;j--;) 333 for(int k=skipcolumns;k<ColumnCounter;k++) 334 Matrix[MatrixCounter][j][k] = value; 335 return true; 336 336 }; 337 337 … … 343 343 bool MatrixContainer::SetLastMatrix(double **values, int skipcolumns) 344 344 { 345 346 347 348 345 for(int j=RowCounter[MatrixCounter]+1;j--;) 346 for(int k=skipcolumns;k<ColumnCounter;k++) 347 Matrix[MatrixCounter][j][k] = values[j][k]; 348 return true; 349 349 }; 350 350 … … 358 358 bool MatrixContainer::SumSubManyBodyTerms(class MatrixContainer &MatrixValues, class KeySetsContainer &KeySet, int Order) 359 359 { 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 387 388 389 390 391 392 393 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 360 // go through each order 361 for (int CurrentFragment=0;CurrentFragment<KeySet.FragmentsPerOrder[Order];CurrentFragment++) { 362 //cout << "Current Fragment is " << CurrentFragment << "/" << KeySet.OrderSet[Order][CurrentFragment] << "." << endl; 363 // then go per order through each suborder and pick together all the terms that contain this fragment 364 for(int SubOrder=0;SubOrder<=Order;SubOrder++) { // go through all suborders up to the desired order 365 for (int j=0;j<KeySet.FragmentsPerOrder[SubOrder];j++) { // go through all possible fragments of size suborder 366 if (KeySet.Contains(KeySet.OrderSet[Order][CurrentFragment], KeySet.OrderSet[SubOrder][j])) { 367 //cout << "Current other fragment is " << j << "/" << KeySet.OrderSet[SubOrder][j] << "." << endl; 368 // if the fragment's indices are all in the current fragment 369 for(int k=0;k<RowCounter[ KeySet.OrderSet[SubOrder][j] ];k++) { // go through all atoms in this fragment 370 int m = MatrixValues.Indices[ KeySet.OrderSet[SubOrder][j] ][k]; 371 //cout << "Current index is " << k << "/" << m << "." << endl; 372 if (m != -1) { // if it's not an added hydrogen 373 for (int l=0;l<RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ];l++) { // look for the corresponding index in the current fragment 374 //cout << "Comparing " << m << " with " << MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][l] << "." << endl; 375 if (m == MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][l]) { 376 m = l; 377 break; 378 } 379 } 380 //cout << "Corresponding index in CurrentFragment is " << m << "." << endl; 381 if (m > RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ]) { 382 cerr << "In fragment No. " << KeySet.OrderSet[Order][CurrentFragment] << " current force index " << m << " is greater than " << RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ] << "!" << endl; 383 return false; 384 } 385 if (Order == SubOrder) { // equal order is always copy from Energies 386 for(int l=ColumnCounter;l--;) // then adds/subtract each column 387 Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][l] += MatrixValues.Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l]; 388 } else { 389 for(int l=ColumnCounter;l--;) 390 Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][l] -= Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l]; 391 } 392 } 393 //if ((ColumnCounter>1) && (RowCounter[0]-1 >= 1)) 394 //cout << "Fragments[ KeySet.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySet.OrderSet[Order][CurrentFragment] << " ][" << RowCounter[0]-1 << "][" << 1 << "] = " << Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][RowCounter[0]-1][1] << endl; 395 } 396 } else { 397 //cout << "Fragment " << KeySet.OrderSet[SubOrder][j] << " is not contained in fragment " << KeySet.OrderSet[Order][CurrentFragment] << "." << endl; 398 } 399 } 400 } 401 //cout << "Final Fragments[ KeySet.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySet.OrderSet[Order][CurrentFragment] << " ][" << KeySet.AtomCounter[0]-1 << "][" << 1 << "] = " << Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][KeySet.AtomCounter[0]-1][1] << endl; 402 } 403 404 return true; 405 405 }; 406 406 … … 412 412 bool MatrixContainer::WriteTotalFragments(const char *name, const char *prefix) 413 413 { 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 414 ofstream output; 415 char *FragmentNumber = NULL; 416 417 cout << "Writing fragment files." << endl; 418 for(int i=0;i<MatrixCounter;i++) { 419 stringstream line; 420 FragmentNumber = FixedDigitNumber(MatrixCounter, i); 421 line << name << FRAGMENTPREFIX << FragmentNumber << "/" << prefix; 422 Free((void **)&FragmentNumber, "*FragmentNumber"); 423 output.open(line.str().c_str(), ios::out); 424 if (output == NULL) { 425 cerr << "Unable to open output energy file " << line.str() << "!" << endl; 426 return false; 427 } 428 output << Header << endl; 429 for(int j=0;j<RowCounter[i];j++) { 430 for(int k=0;k<ColumnCounter;k++) 431 output << scientific << Matrix[i][j][k] << "\t"; 432 output << endl; 433 } 434 output.close(); 435 } 436 return true; 437 437 }; 438 438 … … 445 445 bool MatrixContainer::WriteLastMatrix(const char *name, const char *prefix, const char *suffix) 446 446 { 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 447 ofstream output; 448 stringstream line; 449 450 cout << "Writing matrix values of " << suffix << "." << endl; 451 line << name << prefix << suffix; 452 output.open(line.str().c_str(), ios::out); 453 if (output == NULL) { 454 cerr << "Unable to open output matrix file " << line.str() << "!" << endl; 455 return false; 456 } 457 output << Header << endl; 458 for(int j=0;j<RowCounter[MatrixCounter];j++) { 459 for(int k=0;k<ColumnCounter;k++) 460 output << scientific << Matrix[MatrixCounter][j][k] << "\t"; 461 output << endl; 462 } 463 output.close(); 464 return true; 465 465 }; 466 466 … … 473 473 bool EnergyMatrix::ParseIndices() 474 474 { 475 476 477 478 479 480 481 482 475 cout << "Parsing energy indices." << endl; 476 Indices = (int **) Malloc(sizeof(int *)*(MatrixCounter+1), "EnergyMatrix::ParseIndices: **Indices"); 477 for(int i=MatrixCounter+1;i--;) { 478 Indices[i] = (int *) Malloc(sizeof(int)*RowCounter[i], "EnergyMatrix::ParseIndices: *Indices[]"); 479 for(int j=RowCounter[i];j--;) 480 Indices[i][j] = j; 481 } 482 return true; 483 483 }; 484 484 … … 494 494 bool EnergyMatrix::SumSubEnergy(class EnergyMatrix &Fragments, class EnergyMatrix *CorrectionFragments, class KeySetsContainer &KeySet, int Order, double sign) 495 495 { 496 497 498 499 500 501 502 503 504 505 506 507 496 // sum energy 497 if (CorrectionFragments == NULL) 498 for(int i=KeySet.FragmentsPerOrder[Order];i--;) 499 for(int j=RowCounter[ KeySet.OrderSet[Order][i] ];j--;) 500 for(int k=ColumnCounter;k--;) 501 Matrix[MatrixCounter][j][k] += sign*Fragments.Matrix[ KeySet.OrderSet[Order][i] ][j][k]; 502 else 503 for(int i=KeySet.FragmentsPerOrder[Order];i--;) 504 for(int j=RowCounter[ KeySet.OrderSet[Order][i] ];j--;) 505 for(int k=ColumnCounter;k--;) 506 Matrix[MatrixCounter][j][k] += sign*(Fragments.Matrix[ KeySet.OrderSet[Order][i] ][j][k] + CorrectionFragments->Matrix[ KeySet.OrderSet[Order][i] ][j][k]); 507 return true; 508 508 }; 509 509 … … 518 518 bool EnergyMatrix::ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns) 519 519 { 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 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; 542 542 }; 543 543 … … 550 550 bool ForceMatrix::ParseIndices(char *name) 551 551 { 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 552 ifstream input; 553 char *FragmentNumber = NULL; 554 char filename[1023]; 555 stringstream line; 556 557 cout << "Parsing force indices for " << MatrixCounter << " matrices." << endl; 558 Indices = (int **) Malloc(sizeof(int *)*(MatrixCounter+1), "ForceMatrix::ParseIndices: **Indices"); 559 line << name << FRAGMENTPREFIX << FORCESFILE; 560 input.open(line.str().c_str(), ios::in); 561 //cout << "Opening " << line.str() << " ... " << input << endl; 562 if (input == NULL) { 563 cout << endl << "Unable to open " << line.str() << ", is the directory correct?" << endl; 564 return false; 565 } 566 for (int i=0;(i<MatrixCounter) && (!input.eof());i++) { 567 // get the number of atoms for this fragment 568 input.getline(filename, 1023); 569 line.str(filename); 570 // parse the values 571 Indices[i] = (int *) Malloc(sizeof(int)*RowCounter[i], "ForceMatrix::ParseIndices: *Indices[]"); 572 FragmentNumber = FixedDigitNumber(MatrixCounter, i); 573 //cout << FRAGMENTPREFIX << FragmentNumber << "[" << RowCounter[i] << "]:"; 574 Free((void **)&FragmentNumber, "ForceMatrix::ParseIndices: *FragmentNumber"); 575 for(int j=0;(j<RowCounter[i]) && (!line.eof());j++) { 576 line >> Indices[i][j]; 577 //cout << " " << Indices[i][j]; 578 } 579 //cout << endl; 580 } 581 Indices[MatrixCounter] = (int *) Malloc(sizeof(int)*RowCounter[MatrixCounter], "ForceMatrix::ParseIndices: *Indices[]"); 582 for(int j=RowCounter[MatrixCounter];j--;) { 583 Indices[MatrixCounter][j] = j; 584 } 585 input.close(); 586 return true; 587 587 }; 588 588 … … 592 592 * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order 593 593 * \param Order bond order 594 * 594 * \param sign +1 or -1 595 595 * \return true if summing was successful 596 596 */ 597 597 bool ForceMatrix::SumSubForces(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign) 598 598 { 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 599 int FragmentNr; 600 // sum forces 601 for(int i=0;i<KeySet.FragmentsPerOrder[Order];i++) { 602 FragmentNr = KeySet.OrderSet[Order][i]; 603 for(int l=0;l<RowCounter[ FragmentNr ];l++) { 604 int j = Indices[ FragmentNr ][l]; 605 if (j > RowCounter[MatrixCounter]) { 606 cerr << "Current force index " << j << " is greater than " << RowCounter[MatrixCounter] << "!" << endl; 607 return false; 608 } 609 if (j != -1) { 610 //if (j == 0) cout << "Summing onto ion 0, type 0 from fragment " << FragmentNr << ", ion " << l << "." << endl; 611 for(int k=2;k<ColumnCounter;k++) 612 Matrix[MatrixCounter][j][k] += sign*Fragments.Matrix[ FragmentNr ][l][k]; 613 } 614 } 615 } 616 return true; 617 617 }; 618 618 … … 628 628 bool ForceMatrix::ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns) 629 629 { 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 RowCounter[MatrixCounter]++;// nr start at 0, count starts at 1656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 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; 673 673 }; 674 674 … … 678 678 */ 679 679 KeySetsContainer::KeySetsContainer() { 680 681 682 683 684 685 680 KeySets = NULL; 681 AtomCounter = NULL; 682 FragmentCounter = 0; 683 Order = 0; 684 FragmentsPerOrder = 0; 685 OrderSet = NULL; 686 686 }; 687 687 … … 689 689 */ 690 690 KeySetsContainer::~KeySetsContainer() { 691 692 693 694 695 696 697 698 691 for(int i=FragmentCounter;i--;) 692 Free((void **)&KeySets[i], "KeySetsContainer::~KeySetsContainer: *KeySets[]"); 693 for(int i=Order;i--;) 694 Free((void **)&OrderSet[i], "KeySetsContainer::~KeySetsContainer: *OrderSet[]"); 695 Free((void **)&KeySets, "KeySetsContainer::~KeySetsContainer: **KeySets"); 696 Free((void **)&OrderSet, "KeySetsContainer::~KeySetsContainer: **OrderSet"); 697 Free((void **)&AtomCounter, "KeySetsContainer::~KeySetsContainer: *AtomCounter"); 698 Free((void **)&FragmentsPerOrder, "KeySetsContainer::~KeySetsContainer: *FragmentsPerOrder"); 699 699 }; 700 700 … … 706 706 */ 707 707 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 708 ifstream input; 709 char *FragmentNumber = NULL; 710 stringstream file; 711 char filename[1023]; 712 713 FragmentCounter = FCounter; 714 cout << "Parsing key sets." << endl; 715 KeySets = (int **) Malloc(sizeof(int *)*FragmentCounter, "KeySetsContainer::ParseKeySets: **KeySets"); 716 for(int i=FragmentCounter;i--;) 717 KeySets[i] = NULL; 718 file << name << FRAGMENTPREFIX << KEYSETFILE; 719 input.open(file.str().c_str(), ios::in); 720 if (input == NULL) { 721 cout << endl << "Unable to open " << file.str() << ", is the directory correct?" << endl; 722 return false; 723 } 724 725 AtomCounter = (int *) Malloc(sizeof(int)*FragmentCounter, "KeySetsContainer::ParseKeySets: *RowCounter"); 726 for(int i=0;(i<FragmentCounter) && (!input.eof());i++) { 727 stringstream line; 728 AtomCounter[i] = ACounter[i]; 729 // parse the values 730 KeySets[i] = (int *) Malloc(sizeof(int)*AtomCounter[i], "KeySetsContainer::ParseKeySets: *KeySets[]"); 731 for(int j=AtomCounter[i];j--;) 732 KeySets[i][j] = -1; 733 FragmentNumber = FixedDigitNumber(FragmentCounter, i); 734 //cout << FRAGMENTPREFIX << FragmentNumber << "[" << AtomCounter[i] << "]:"; 735 Free((void **)&FragmentNumber, "KeySetsContainer::ParseKeySets: *FragmentNumber"); 736 input.getline(filename, 1023); 737 line.str(filename); 738 for(int j=0;(j<AtomCounter[i]) && (!line.eof());j++) { 739 line >> KeySets[i][j]; 740 //cout << " " << KeySets[i][j]; 741 } 742 //cout << endl; 743 } 744 input.close(); 745 return true; 746 746 }; 747 747 … … 751 751 bool KeySetsContainer::ParseManyBodyTerms() 752 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 798 799 800 801 802 803 804 805 806 753 int Counter; 754 755 cout << "Creating Fragment terms." << endl; 756 // scan through all to determine maximum order 757 Order=0; 758 for(int i=FragmentCounter;i--;) { 759 Counter=0; 760 for(int j=AtomCounter[i];j--;) 761 if (KeySets[i][j] != -1) 762 Counter++; 763 if (Counter > Order) 764 Order = Counter; 765 } 766 cout << "Found Order is " << Order << "." << endl; 767 768 // scan through all to determine fragments per order 769 FragmentsPerOrder = (int *) Malloc(sizeof(int)*Order, "KeySetsContainer::ParseManyBodyTerms: *FragmentsPerOrder"); 770 for(int i=Order;i--;) 771 FragmentsPerOrder[i] = 0; 772 for(int i=FragmentCounter;i--;) { 773 Counter=0; 774 for(int j=AtomCounter[i];j--;) 775 if (KeySets[i][j] != -1) 776 Counter++; 777 FragmentsPerOrder[Counter-1]++; 778 } 779 for(int i=0;i<Order;i++) 780 cout << "Found No. of Fragments of Order " << i+1 << " is " << FragmentsPerOrder[i] << "." << endl; 781 782 // scan through all to gather indices to each order set 783 OrderSet = (int **) Malloc(sizeof(int *)*Order, "KeySetsContainer::ParseManyBodyTerms: **OrderSet"); 784 for(int i=Order;i--;) 785 OrderSet[i] = (int *) Malloc(sizeof(int)*FragmentsPerOrder[i], "KeySetsContainer::ParseManyBodyTermsKeySetsContainer::ParseManyBodyTerms: *OrderSet[]"); 786 for(int i=Order;i--;) 787 FragmentsPerOrder[i] = 0; 788 for(int i=FragmentCounter;i--;) { 789 Counter=0; 790 for(int j=AtomCounter[i];j--;) 791 if (KeySets[i][j] != -1) 792 Counter++; 793 OrderSet[Counter-1][FragmentsPerOrder[Counter-1]] = i; 794 FragmentsPerOrder[Counter-1]++; 795 } 796 cout << "Printing OrderSet." << endl; 797 for(int i=0;i<Order;i++) { 798 for (int j=0;j<FragmentsPerOrder[i];j++) { 799 cout << " " << OrderSet[i][j]; 800 } 801 cout << endl; 802 } 803 cout << endl; 804 805 806 return true; 807 807 }; 808 808 … … 814 814 bool KeySetsContainer::Contains(const int GreaterSet, const int SmallerSet) 815 815 { 816 817 818 819 820 821 822 823 824 825 826 827 816 bool result = true; 817 bool intermediate; 818 if ((GreaterSet < 0) || (SmallerSet < 0) || (GreaterSet > FragmentCounter) || (SmallerSet > FragmentCounter)) // index out of bounds 819 return false; 820 for(int i=AtomCounter[SmallerSet];i--;) { 821 intermediate = false; 822 for (int j=AtomCounter[GreaterSet];j--;) 823 intermediate = (intermediate || ((KeySets[SmallerSet][i] == KeySets[GreaterSet][j]) || (KeySets[SmallerSet][i] == -1))); 824 result = result && intermediate; 825 } 826 827 return result; 828 828 }; 829 829 -
src/parser.hpp
r178f92 r437922 40 40 41 41 class MatrixContainer { 42 43 44 45 46 47 48 42 public: 43 double ***Matrix; 44 int **Indices; 45 char *Header; 46 int MatrixCounter; 47 int *RowCounter; 48 int ColumnCounter; 49 49 50 51 50 MatrixContainer(); 51 virtual ~MatrixContainer(); 52 52 53 54 55 56 57 58 59 60 61 62 63 64 65 53 bool ParseMatrix(const char *name, int skiplines, int skipcolumns, int MatrixNr); 54 virtual bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns); 55 bool AllocateMatrix(char *GivenHeader, int MCounter, int *RCounter, int CCounter); 56 bool ResetMatrix(); 57 double FindMinValue(); 58 double FindMaxValue(); 59 bool SetLastMatrix(double value, int skipcolumns); 60 bool SetLastMatrix(double **values, int skipcolumns); 61 //bool ParseIndices(); 62 //bool SumSubValues(); 63 bool SumSubManyBodyTerms(class MatrixContainer &Matrix, class KeySetsContainer &KeySet, int Order); 64 bool WriteTotalFragments(const char *name, const char *prefix); 65 bool WriteLastMatrix(const char *name, const char *prefix, const char *suffix); 66 66 }; 67 67 … … 69 69 70 70 class EnergyMatrix : public MatrixContainer { 71 72 73 74 71 public: 72 bool ParseIndices(); 73 bool SumSubEnergy(class EnergyMatrix &Fragments, class EnergyMatrix *CorrectionFragments, class KeySetsContainer &KeySet, int Order, double sign); 74 bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns); 75 75 }; 76 76 … … 78 78 79 79 class ForceMatrix : public MatrixContainer { 80 81 82 83 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); 84 84 }; 85 85 … … 87 87 88 88 class KeySetsContainer { 89 90 91 92 93 94 95 89 public: 90 int **KeySets; 91 int *AtomCounter; 92 int FragmentCounter; 93 int Order; 94 int *FragmentsPerOrder; 95 int **OrderSet; 96 96 97 98 97 KeySetsContainer(); 98 ~KeySetsContainer(); 99 99 100 101 102 100 bool ParseKeySets(const char *name, const int *ACounter, const int FCounter); 101 bool ParseManyBodyTerms(); 102 bool Contains(const int GreaterSet, const int SmallerSet); 103 103 }; 104 104 -
src/periodentafel.cpp
r178f92 r437922 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 };
Note:
See TracChangeset
for help on using the changeset viewer.