Changeset 042f82
- Timestamp:
- Jul 23, 2009, 2:21:57 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:
- 36ec71
- Parents:
- 205ccd
- Location:
- src
- Files:
-
- 28 edited
Legend:
- Unmodified
- Added
- Removed
-
src/analyzer.cpp
r205ccd r042f82 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
r205ccd r042f82 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
r205ccd r042f82 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
r205ccd r042f82 239 239 240 240 CandidateForTesselation::CandidateForTesselation( 241 241 atom *candidate, BoundaryLineSet* line, Vector OptCandidateCenter, Vector OtherOptCandidateCenter 242 242 ) { 243 244 245 246 243 point = candidate; 244 BaseLine = line; 245 OptCenter.CopyVector(&OptCandidateCenter); 246 OtherOptCenter.CopyVector(&OtherOptCandidateCenter); 247 247 } 248 248 249 249 CandidateForTesselation::~CandidateForTesselation() { 250 251 250 point = NULL; 251 BaseLine = NULL; 252 252 } 253 253 … … 1904 1904 Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in 1905 1905 Vector SphereCenter; 1906 Vector NewSphereCenter; 1907 Vector OtherNewSphereCenter; 1906 Vector NewSphereCenter; // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility 1907 Vector OtherNewSphereCenter; // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility 1908 1908 Vector NewNormalVector; // normal vector of the Candidate's triangle 1909 1909 Vector helper, OptCandidateCenter, OtherOptCandidateCenter; … … 1985 1985 1986 1986 if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) 1987 1987 && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON) 1988 1988 ) { 1989 1989 helper.CopyVector(&NewNormalVector); … … 2072 2072 //cout << Verbose(2) << "INFO: Sorting candidate list ..." << endl; 2073 2073 if (candidates->size() > 1) { 2074 2075 2074 candidates->unique(); 2075 candidates->sort(sortCandidates); 2076 2076 } 2077 2077 … … 2080 2080 2081 2081 struct Intersection { 2082 2083 2084 2085 2082 Vector x1; 2083 Vector x2; 2084 Vector x3; 2085 Vector x4; 2086 2086 }; 2087 2087 … … 2093 2093 */ 2094 2094 double MinIntersectDistance(const gsl_vector * x, void *params) { 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2095 double retval = 0; 2096 struct Intersection *I = (struct Intersection *)params; 2097 Vector intersection; 2098 Vector SideA,SideB,HeightA, HeightB; 2099 for (int i=0;i<NDIM;i++) 2100 intersection.x[i] = gsl_vector_get(x, i); 2101 2102 SideA.CopyVector(&(I->x1)); 2103 SideA.SubtractVector(&I->x2); 2104 HeightA.CopyVector(&intersection); 2105 HeightA.SubtractVector(&I->x1); 2106 HeightA.ProjectOntoPlane(&SideA); 2107 2108 SideB.CopyVector(&I->x3); 2109 SideB.SubtractVector(&I->x4); 2110 HeightB.CopyVector(&intersection); 2111 HeightB.SubtractVector(&I->x3); 2112 HeightB.ProjectOntoPlane(&SideB); 2113 2114 retval = HeightA.ScalarProduct(&HeightA) + HeightB.ScalarProduct(&HeightB); 2115 //cout << Verbose(2) << "MinIntersectDistance called, result: " << retval << endl; 2116 2117 return retval; 2118 2118 }; 2119 2119 … … 2132 2132 */ 2133 2133 bool existsIntersection(Vector point1, Vector point2, Vector point3, Vector point4) { 2134 2135 2136 2137 2138 2139 2140 2134 bool result; 2135 2136 struct Intersection par; 2137 par.x1.CopyVector(&point1); 2138 par.x2.CopyVector(&point2); 2139 par.x3.CopyVector(&point3); 2140 par.x4.CopyVector(&point4); 2141 2141 2142 2142 const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex; … … 2179 2179 2180 2180 if (status == GSL_SUCCESS) { 2181 2181 cout << Verbose(2) << "converged to minimum" << endl; 2182 2182 } 2183 2183 } while (status == GSL_CONTINUE && iter < 100); 2184 2184 2185 2185 // check whether intersection is in between or not 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2186 Vector intersection, SideA, SideB, HeightA, HeightB; 2187 double t1, t2; 2188 for (int i = 0; i < NDIM; i++) { 2189 intersection.x[i] = gsl_vector_get(s->x, i); 2190 } 2191 2192 SideA.CopyVector(&par.x2); 2193 SideA.SubtractVector(&par.x1); 2194 HeightA.CopyVector(&intersection); 2195 HeightA.SubtractVector(&par.x1); 2196 2197 t1 = HeightA.Projection(&SideA)/SideA.ScalarProduct(&SideA); 2198 2199 SideB.CopyVector(&par.x4); 2200 SideB.SubtractVector(&par.x3); 2201 HeightB.CopyVector(&intersection); 2202 HeightB.SubtractVector(&par.x3); 2203 2204 t2 = HeightB.Projection(&SideB)/SideB.ScalarProduct(&SideB); 2205 2206 cout << Verbose(2) << "Intersection " << intersection << " is at " 2207 << t1 << " for (" << point1 << "," << point2 << ") and at " 2208 << t2 << " for (" << point3 << "," << point4 << "): "; 2209 2210 if (((t1 >= 0) && (t1 <= 1)) && ((t2 >= 0) && (t2 <= 1))) { 2211 cout << "true intersection." << endl; 2212 result = true; 2213 } else { 2214 cout << "intersection out of region of interest." << endl; 2215 result = false; 2216 } 2217 2218 // free minimizer stuff 2219 2219 gsl_vector_free(x); 2220 2220 gsl_vector_free(ss); 2221 2221 gsl_multimin_fminimizer_free(s); 2222 2222 2223 2223 return result; 2224 2224 } 2225 2225 … … 2603 2603 cout << Verbose(1) << "Third Points are "; 2604 2604 for (CandidateList::iterator it = Opt_Candidates->begin(); it != Opt_Candidates->end(); ++it) { 2605 2605 cout << " " << *(*it)->point; 2606 2606 } 2607 2607 cout << endl; … … 2609 2609 BoundaryLineSet *BaseRay = &Line; 2610 2610 for (CandidateList::iterator it = Opt_Candidates->begin(); it != Opt_Candidates->end(); ++it) { 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2611 cout << Verbose(1) << " Third point candidate is " << *(*it)->point 2612 << " with circumsphere's center at " << (*it)->OptCenter << "." << endl; 2613 cout << Verbose(1) << " Baseline is " << *BaseRay << endl; 2614 2615 // check whether all edges of the new triangle still have space for one more triangle (i.e. TriangleCount <2) 2616 atom *AtomCandidates[3]; 2617 AtomCandidates[0] = (*it)->point; 2618 AtomCandidates[1] = BaseRay->endpoints[0]->node; 2619 AtomCandidates[2] = BaseRay->endpoints[1]->node; 2620 int existentTrianglesCount = CheckPresenceOfTriangle(out, AtomCandidates); 2621 2622 BTS = NULL; 2623 // If there is no triangle, add it regularly. 2624 if (existentTrianglesCount == 0) { 2625 2625 AddTrianglePoint((*it)->point, 0); 2626 2626 AddTrianglePoint(BaseRay->endpoints[0]->node, 1); … … 2640 2640 << " for this triangle ... " << endl; 2641 2641 //cout << Verbose(1) << "We have "<< TrianglesOnBoundaryCount << " for line " << *BaseRay << "." << endl; 2642 2642 } else if (existentTrianglesCount == 1) { // If there is a planar region within the structure, we need this triangle a second time. 2643 2643 AddTrianglePoint((*it)->point, 0); 2644 2644 AddTrianglePoint(BaseRay->endpoints[0]->node, 1); … … 2679 2679 } 2680 2680 2681 2681 if ((result) && (existentTrianglesCount < 2) && (DoSingleStepOutput && (TrianglesOnBoundaryCount % 1 == 0))) { // if we have a new triangle and want to output each new triangle configuration 2682 2682 sprintf(NumberName, "-%04d-%s_%s_%s", TriangleFilesWritten, BTS->endpoints[0]->node->Name, BTS->endpoints[1]->node->Name, BTS->endpoints[2]->node->Name); 2683 2683 if (DoTecplotOutput) { … … 2726 2726 if (DoTecplotOutput || DoRaster3DOutput) 2727 2727 TriangleFilesWritten++; 2728 2728 } 2729 2729 2730 2730 // set baseline to new ray from ref point (here endpoints[0]->node) to current candidate (here (*it)->point)) 2731 2731 BaseRay = BLS[0]; 2732 2732 } 2733 2733 … … 2747 2747 */ 2748 2748 bool sortCandidates(CandidateForTesselation* candidate1, CandidateForTesselation* candidate2) { 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2749 Vector BaseLineVector, OrthogonalVector, helper; 2750 if (candidate1->BaseLine != candidate2->BaseLine) { // sanity check 2751 cout << Verbose(0) << "ERROR: sortCandidates was called for two different baselines: " << candidate1->BaseLine << " and " << candidate2->BaseLine << "." << endl; 2752 //return false; 2753 exit(1); 2754 } 2755 // create baseline vector 2756 BaseLineVector.CopyVector(&(candidate1->BaseLine->endpoints[1]->node->x)); 2757 BaseLineVector.SubtractVector(&(candidate1->BaseLine->endpoints[0]->node->x)); 2758 BaseLineVector.Normalize(); 2759 2759 2760 2760 // create normal in-plane vector to cope with acos() non-uniqueness on [0,2pi] (note that is pointing in the "right" direction already, hence ">0" test!) 2761 2762 2763 2764 2765 2766 2761 helper.CopyVector(&(candidate1->BaseLine->endpoints[0]->node->x)); 2762 helper.SubtractVector(&(candidate1->point->x)); 2763 OrthogonalVector.CopyVector(&helper); 2764 helper.VectorProduct(&BaseLineVector); 2765 OrthogonalVector.SubtractVector(&helper); 2766 OrthogonalVector.Normalize(); 2767 2767 2768 2768 // calculate both angles and correct with in-plane vector 2769 2770 2771 2769 helper.CopyVector(&(candidate1->point->x)); 2770 helper.SubtractVector(&(candidate1->BaseLine->endpoints[0]->node->x)); 2771 double phi = BaseLineVector.Angle(&helper); 2772 2772 if (OrthogonalVector.ScalarProduct(&helper) > 0) { 2773 2773 phi = 2.*M_PI - phi; 2774 2774 } 2775 2775 helper.CopyVector(&(candidate2->point->x)); 2776 2777 2776 helper.SubtractVector(&(candidate1->BaseLine->endpoints[0]->node->x)); 2777 double psi = BaseLineVector.Angle(&helper); 2778 2778 if (OrthogonalVector.ScalarProduct(&helper) > 0) { 2779 2780 2781 2782 2783 2784 2785 2786 2779 psi = 2.*M_PI - psi; 2780 } 2781 2782 cout << Verbose(2) << *candidate1->point << " has angle " << phi << endl; 2783 cout << Verbose(2) << *candidate2->point << " has angle " << psi << endl; 2784 2785 // return comparison 2786 return phi < psi; 2787 2787 } 2788 2788 -
src/boundary.hpp
r205ccd r042f82 78 78 class CandidateForTesselation { 79 79 public : 80 81 82 83 84 85 80 CandidateForTesselation(atom* candidate, BoundaryLineSet* currentBaseLine, Vector OptCandidateCenter, Vector OtherOptCandidateCenter); 81 ~CandidateForTesselation(); 82 atom *point; 83 BoundaryLineSet *BaseLine; 84 Vector OptCenter; 85 Vector OtherOptCenter; 86 86 }; 87 87 -
src/builder.cpp
r205ccd r042f82 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, &x); 285 break; 286 case 'b': 287 cout << Verbose(0) << "Centering atoms in config file on center of gravity." << endl; 288 mol->CenterGravity((ofstream *)&cout, &x); 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->Translate(&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); 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 … … 1038 1038 static void testroutine(MoleculeListClass *molecules) 1039 1039 { 1040 1041 1040 // the current test routine checks the functionality of the KeySet&Graph concept: 1041 // We want to have a multiindex (the KeySet) describing a unique subgraph 1042 1042 int i, comp, counter=0; 1043 1043 … … 1052 1052 atom *Walker = mol->start; 1053 1053 1054 1055 1056 1057 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 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 while (A !=Subgraphs.end()) {1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1054 // generate some KeySets 1055 cout << "Generating KeySets." << endl; 1056 KeySet TestSets[mol->AtomCount+1]; 1057 i=1; 1058 while (Walker->next != mol->end) { 1059 Walker = Walker->next; 1060 for (int j=0;j<i;j++) { 1061 TestSets[j].insert(Walker->nr); 1062 } 1063 i++; 1064 } 1065 cout << "Testing insertion of already present item in KeySets." << endl; 1066 KeySetTestPair test; 1067 test = TestSets[mol->AtomCount-1].insert(Walker->nr); 1068 if (test.second) { 1069 cout << Verbose(1) << "Insertion worked?!" << endl; 1070 } else { 1071 cout << Verbose(1) << "Insertion rejected: Present object is " << (*test.first) << "." << endl; 1072 } 1073 TestSets[mol->AtomCount].insert(mol->end->previous->nr); 1074 TestSets[mol->AtomCount].insert(mol->end->previous->previous->previous->nr); 1075 1076 // constructing Graph structure 1077 cout << "Generating Subgraph class." << endl; 1078 Graph Subgraphs; 1079 1080 // insert KeySets into Subgraphs 1081 cout << "Inserting KeySets into Subgraph class." << endl; 1082 for (int j=0;j<mol->AtomCount;j++) { 1083 Subgraphs.insert(GraphPair (TestSets[j],pair<int, double>(counter++, 1.))); 1084 } 1085 cout << "Testing insertion of already present item in Subgraph." << endl; 1086 GraphTestPair test2; 1087 test2 = Subgraphs.insert(GraphPair (TestSets[mol->AtomCount],pair<int, double>(counter++, 1.))); 1088 if (test2.second) { 1089 cout << Verbose(1) << "Insertion worked?!" << endl; 1090 } else { 1091 cout << Verbose(1) << "Insertion rejected: Present object is " << (*(test2.first)).second.first << "." << endl; 1092 } 1093 1094 // show graphs 1095 cout << "Showing Subgraph's contents, checking that it's sorted." << endl; 1096 Graph::iterator A = Subgraphs.begin(); 1097 while (A != Subgraphs.end()) { 1098 cout << (*A).second.first << ": "; 1099 KeySet::iterator key = (*A).first.begin(); 1100 comp = -1; 1101 while (key != (*A).first.end()) { 1102 if ((*key) > comp) 1103 cout << (*key) << " "; 1104 else 1105 cout << (*key) << "! "; 1106 comp = (*key); 1107 key++; 1108 } 1109 cout << endl; 1110 A++; 1111 } 1112 delete(mol); 1113 1113 }; 1114 1114 … … 1121 1121 static void SaveConfig(char *ConfigFileName, config *configuration, periodentafel *periode, MoleculeListClass *molecules) 1122 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 1195 1196 1197 1123 char filename[MAXSTRINGSIZE]; 1124 ofstream output; 1125 molecule *mol = new molecule(periode); 1126 1127 // merge all molecules in MoleculeListClass into this molecule 1128 int N = molecules->ListOfMolecules.size(); 1129 int *src = new int(N); 1130 N=0; 1131 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) 1132 src[N++] = (*ListRunner)->IndexNr; 1133 molecules->SimpleMultiAdd(mol, src, N); 1134 1135 cout << Verbose(0) << "Storing configuration ... " << endl; 1136 // get correct valence orbitals 1137 mol->CalculateOrbitals(*configuration); 1138 configuration->InitMaxMinStopStep = configuration->MaxMinStopStep = configuration->MaxPsiDouble; 1139 strcpy(filename, ConfigFileName); 1140 if (ConfigFileName != NULL) { // test the file name 1141 output.open(ConfigFileName, ios::trunc); 1142 } else if (strlen(configuration->configname) != 0) { 1143 strcpy(filename, configuration->configname); 1144 output.open(configuration->configname, ios::trunc); 1145 } else { 1146 strcpy(filename, DEFAULTCONFIG); 1147 output.open(DEFAULTCONFIG, ios::trunc); 1148 } 1149 output.close(); 1150 output.clear(); 1151 cout << Verbose(0) << "Saving of config file "; 1152 if (configuration->Save(filename, periode, mol)) 1153 cout << "successful." << endl; 1154 else 1155 cout << "failed." << endl; 1156 1157 // and save to xyz file 1158 if (ConfigFileName != NULL) { 1159 strcpy(filename, ConfigFileName); 1160 strcat(filename, ".xyz"); 1161 output.open(filename, ios::trunc); 1162 } 1163 if (output == NULL) { 1164 strcpy(filename,"main_pcp_linux"); 1165 strcat(filename, ".xyz"); 1166 output.open(filename, ios::trunc); 1167 } 1168 cout << Verbose(0) << "Saving of XYZ file "; 1169 if (mol->MDSteps <= 1) { 1170 if (mol->OutputXYZ(&output)) 1171 cout << "successful." << endl; 1172 else 1173 cout << "failed." << endl; 1174 } else { 1175 if (mol->OutputTrajectoriesXYZ(&output)) 1176 cout << "successful." << endl; 1177 else 1178 cout << "failed." << endl; 1179 } 1180 output.close(); 1181 output.clear(); 1182 1183 // and save as MPQC configuration 1184 if (ConfigFileName != NULL) 1185 strcpy(filename, ConfigFileName); 1186 if (output == NULL) 1187 strcpy(filename,"main_pcp_linux"); 1188 cout << Verbose(0) << "Saving as mpqc input "; 1189 if (configuration->SaveMPQC(filename, mol)) 1190 cout << "done." << endl; 1191 else 1192 cout << "failed." << endl; 1193 1194 if (!strcmp(configuration->configpath, configuration->GetDefaultPath())) { 1195 cerr << "WARNING: config is found under different path then stated in config file::defaultpath!" << endl; 1196 } 1197 delete(mol); 1198 1198 }; 1199 1199 … … 1210 1210 static int ParseCommandLineOptions(int argc, char **argv, MoleculeListClass *&molecules, periodentafel *&periode, config& configuration, char *&ConfigFileName) 1211 1211 { 1212 Vector x,y,z,n;// coordinates for absolute point in cell volume1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1212 Vector x,y,z,n; // coordinates for absolute point in cell volume 1213 double *factor; // unit factor if desired 1214 ifstream test; 1215 ofstream output; 1216 string line; 1217 atom *first; 1218 bool SaveFlag = false; 1219 int ExitFlag = 0; 1220 int j; 1221 double volume = 0.; 1222 enum ConfigStatus config_present = absent; 1223 clock_t start,end; 1224 int argptr; 1225 1225 strncpy(configuration.databasepath, LocalPath, MAXSTRINGSIZE-1); 1226 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 1227 // simply create a new molecule, wherein the config file is loaded and the manipulation takes place 1228 molecule *mol = new molecule(periode); 1229 molecules->insert(mol); 1230 1231 if (argc > 1) { // config file specified as option 1232 // 1. : Parse options that just set variables or print help 1233 argptr = 1; 1234 do { 1235 if (argv[argptr][0] == '-') { 1236 cout << Verbose(0) << "Recognized command line argument: " << argv[argptr][1] << ".\n"; 1237 argptr++; 1238 switch(argv[argptr-1][1]) { 1239 case 'h': 1240 case 'H': 1241 case '?': 1242 cout << "MoleCuilder suite" << endl << "==================" << endl << endl; 1243 cout << "Usage: " << argv[0] << "[config file] [-{acefpsthH?vfrp}] [further arguments]" << endl; 1244 cout << "or simply " << argv[0] << " without arguments for interactive session." << endl; 1245 cout << "\t-a Z x1 x2 x3\tAdd new atom of element Z at coordinates (x1,x2,x3)." << endl; 1246 cout << "\t-A <source>\tCreate adjacency list from bonds parsed from 'dbond'-style file." <<endl; 1247 cout << "\t-b xx xy xz yy yz zz\tCenter atoms in domain with given symmetric matrix of (xx,xy,xz,yy,yz,zz)." << endl; 1248 cout << "\t-B <basis>\tSetting basis to store to MPQC config files." << endl; 1249 cout << "\t-c x1 x2 x3\tCenter atoms in domain with a minimum distance to boundary of (x1,x2,x3)." << endl; 1250 cout << "\t-D <bond distance>\tDepth-First-Search Analysis of the molecule, giving cycles and tree/back edges." << endl; 1251 cout << "\t-O\tCenter atoms in origin." << endl; 1252 cout << "\t-d x1 x2 x3\tDuplicate cell along each axis by given factor." << endl; 1253 cout << "\t-e <file>\tSets the databases path to be parsed (default: ./)." << endl; 1254 cout << "\t-E <id> <Z>\tChange atom <id>'s element to <Z>, <id> begins at 0." << endl; 1255 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; 1256 cout << "\t-h/-H/-?\tGive this help screen." << endl; 1257 cout << "\t-m <0/1>\tCalculate (0)/ Align in(1) PAS with greatest EV along z axis." << endl; 1258 cout << "\t-n\tFast parsing (i.e. no trajectories are looked for)." << endl; 1259 cout << "\t-N\tGet non-convex-envelope." << endl; 1260 cout << "\t-o <out>\tGet volume of the convex envelope (and store to tecplot file)." << endl; 1261 cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl; 1262 cout << "\t-P <file>\tParse given forces file and append as an MD step to config file via Verlet." << endl; 1263 cout << "\t-r\t\tConvert file from an old pcp syntax." << endl; 1264 cout << "\t-t x1 x2 x3\tTranslate all atoms by this vector (x1,x2,x3)." << endl; 1265 1265 cout << "\t-T x1 x2 x3\tTranslate periodically all atoms by this vector (x1,x2,x3)." << endl; 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 1292 1293 1294 1295 1296 default:// no match? Step on1297 1298 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 mol->AddAtom(first);// add to molecule1390 1391 1392 1393 1394 1395 1396 1397 default:// no match? Don't step on (this is done in next switch's default)1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 MoleculeLeafClass *Subgraphs = NULL;// list of subgraphs from DFS analysis1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 Subgraphs->next->FillBondStructureFromReference((ofstream *)&cout, mol, (FragmentCounter = 0), ListOfLocalAtoms, false);// we want to keep the created ListOfLocalAtoms1428 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 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 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1266 cout << "\t-S <file> Store temperatures from the config file in <file>." << endl; 1267 cout << "\t-s x1 x2 x3\tScale all atom coordinates by this vector (x1,x2,x3)." << endl; 1268 cout << "\t-u rho\tsuspend in water solution and output necessary cell lengths, average density rho and repetition." << endl; 1269 cout << "\t-v/-V\t\tGives version information." << endl; 1270 cout << "Note: config files must not begin with '-' !" << endl; 1271 delete(mol); 1272 delete(periode); 1273 return (1); 1274 break; 1275 case 'v': 1276 case 'V': 1277 cout << argv[0] << " " << VERSIONSTRING << endl; 1278 cout << "Build your own molecule position set." << endl; 1279 delete(mol); 1280 delete(periode); 1281 return (1); 1282 break; 1283 case 'e': 1284 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1285 cerr << "Not enough or invalid arguments for specifying element db: -e <db file>" << endl; 1286 } else { 1287 cout << "Using " << argv[argptr] << " as elements database." << endl; 1288 strncpy (configuration.databasepath, argv[argptr], MAXSTRINGSIZE-1); 1289 argptr+=1; 1290 } 1291 break; 1292 case 'n': 1293 cout << "I won't parse trajectories." << endl; 1294 configuration.FastParsing = true; 1295 break; 1296 default: // no match? Step on 1297 argptr++; 1298 break; 1299 } 1300 } else 1301 argptr++; 1302 } while (argptr < argc); 1303 1304 // 2. Parse the element database 1305 if (periode->LoadPeriodentafel(configuration.databasepath)) { 1306 cout << Verbose(0) << "Element list loaded successfully." << endl; 1307 //periode->Output((ofstream *)&cout); 1308 } else { 1309 cout << Verbose(0) << "Element list loading failed." << endl; 1310 return 1; 1311 } 1312 // 3. Find config file name and parse if possible 1313 if (argv[1][0] != '-') { 1314 cout << Verbose(0) << "Config file given." << endl; 1315 test.open(argv[1], ios::in); 1316 if (test == NULL) { 1317 //return (1); 1318 output.open(argv[1], ios::out); 1319 if (output == NULL) { 1320 cout << Verbose(1) << "Specified config file " << argv[1] << " not found." << endl; 1321 config_present = absent; 1322 } else { 1323 cout << "Empty configuration file." << endl; 1324 ConfigFileName = argv[1]; 1325 config_present = empty; 1326 output.close(); 1327 } 1328 } else { 1329 test.close(); 1330 ConfigFileName = argv[1]; 1331 cout << Verbose(1) << "Specified config file found, parsing ... "; 1332 switch (configuration.TestSyntax(ConfigFileName, periode, mol)) { 1333 case 1: 1334 cout << "new syntax." << endl; 1335 configuration.Load(ConfigFileName, periode, mol); 1336 config_present = present; 1337 break; 1338 case 0: 1339 cout << "old syntax." << endl; 1340 configuration.LoadOld(ConfigFileName, periode, mol); 1341 config_present = present; 1342 break; 1343 default: 1344 cout << "Unknown syntax or empty, yet present file." << endl; 1345 config_present = empty; 1346 } 1347 } 1348 } else 1349 config_present = absent; 1350 // 4. parse again through options, now for those depending on elements db and config presence 1351 argptr = 1; 1352 do { 1353 cout << "Current Command line argument: " << argv[argptr] << "." << endl; 1354 if (argv[argptr][0] == '-') { 1355 argptr++; 1356 if ((config_present == present) || (config_present == empty)) { 1357 switch(argv[argptr-1][1]) { 1358 case 'p': 1359 ExitFlag = 1; 1360 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1361 ExitFlag = 255; 1362 cerr << "Not enough arguments for parsing: -p <xyz file>" << endl; 1363 } else { 1364 SaveFlag = true; 1365 cout << Verbose(1) << "Parsing xyz file for new atoms." << endl; 1366 if (!mol->AddXYZFile(argv[argptr])) 1367 cout << Verbose(2) << "File not found." << endl; 1368 else { 1369 cout << Verbose(2) << "File found and parsed." << endl; 1370 config_present = present; 1371 } 1372 } 1373 break; 1374 case 'a': 1375 ExitFlag = 1; 1376 if ((argptr >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr+1]))) { 1377 ExitFlag = 255; 1378 cerr << "Not enough or invalid arguments for adding atom: -a <element> <x> <y> <z>" << endl; 1379 } else { 1380 SaveFlag = true; 1381 cout << Verbose(1) << "Adding new atom with element " << argv[argptr] << " at (" << argv[argptr+1] << "," << argv[argptr+2] << "," << argv[argptr+3] << "), "; 1382 first = new atom; 1383 first->type = periode->FindElement(atoi(argv[argptr])); 1384 if (first->type != NULL) 1385 cout << Verbose(2) << "found element " << first->type->name << endl; 1386 for (int i=NDIM;i--;) 1387 first->x.x[i] = atof(argv[argptr+1+i]); 1388 if (first->type != NULL) { 1389 mol->AddAtom(first); // add to molecule 1390 if ((config_present == empty) && (mol->AtomCount != 0)) 1391 config_present = present; 1392 } else 1393 cerr << Verbose(1) << "Could not find the specified element." << endl; 1394 argptr+=4; 1395 } 1396 break; 1397 default: // no match? Don't step on (this is done in next switch's default) 1398 break; 1399 } 1400 } 1401 if (config_present == present) { 1402 switch(argv[argptr-1][1]) { 1403 case 'B': 1404 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1405 ExitFlag = 255; 1406 cerr << "Not enough or invalid arguments given for setting MPQC basis: -B <basis name>" << endl; 1407 } else { 1408 configuration.basis = argv[argptr]; 1409 cout << Verbose(1) << "Setting MPQC basis to " << configuration.basis << "." << endl; 1410 argptr+=1; 1411 } 1412 break; 1413 case 'D': 1414 ExitFlag = 1; 1415 { 1416 cout << Verbose(1) << "Depth-First-Search Analysis." << endl; 1417 MoleculeLeafClass *Subgraphs = NULL; // list of subgraphs from DFS analysis 1418 int *MinimumRingSize = new int[mol->AtomCount]; 1419 atom ***ListOfLocalAtoms = NULL; 1420 int FragmentCounter = 0; 1421 class StackClass<bond *> *BackEdgeStack = NULL; 1422 class StackClass<bond *> *LocalBackEdgeStack = NULL; 1423 mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr]), configuration.GetIsAngstroem()); 1424 mol->CreateListOfBondsPerAtom((ofstream *)&cout); 1425 Subgraphs = mol->DepthFirstSearchAnalysis((ofstream *)&cout, BackEdgeStack); 1426 if (Subgraphs != NULL) { 1427 Subgraphs->next->FillBondStructureFromReference((ofstream *)&cout, mol, (FragmentCounter = 0), ListOfLocalAtoms, false); // we want to keep the created ListOfLocalAtoms 1428 while (Subgraphs->next != NULL) { 1429 Subgraphs = Subgraphs->next; 1430 LocalBackEdgeStack = new StackClass<bond *> (Subgraphs->Leaf->BondCount); 1431 Subgraphs->Leaf->PickLocalBackEdges((ofstream *)&cout, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack); 1432 Subgraphs->Leaf->CyclicStructureAnalysis((ofstream *)&cout, BackEdgeStack, MinimumRingSize); 1433 delete(LocalBackEdgeStack); 1434 delete(Subgraphs->previous); 1435 } 1436 delete(Subgraphs); 1437 for (int i=0;i<FragmentCounter;i++) 1438 Free((void **)&ListOfLocalAtoms[FragmentCounter], "ParseCommandLineOptions: **ListOfLocalAtoms[]"); 1439 Free((void **)&ListOfLocalAtoms, "ParseCommandLineOptions: ***ListOfLocalAtoms"); 1440 } 1441 delete(BackEdgeStack); 1442 delete[](MinimumRingSize); 1443 } 1444 //argptr+=1; 1445 break; 1446 case 'E': 1447 ExitFlag = 1; 1448 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (argv[argptr+1][0] == '-')) { 1449 ExitFlag = 255; 1450 cerr << "Not enough or invalid arguments given for changing element: -E <atom nr.> <element>" << endl; 1451 } else { 1452 SaveFlag = true; 1453 cout << Verbose(1) << "Changing atom " << argv[argptr] << " to element " << argv[argptr+1] << "." << endl; 1454 first = mol->FindAtom(atoi(argv[argptr])); 1455 first->type = periode->FindElement(atoi(argv[argptr+1])); 1456 argptr+=2; 1457 } 1458 break; 1459 case 'A': 1460 ExitFlag = 1; 1461 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1462 ExitFlag =255; 1463 cerr << "Missing source file for bonds in molecule: -A <bond sourcefile>" << endl; 1464 } else { 1465 cout << "Parsing bonds from " << argv[argptr] << "." << endl; 1466 ifstream *input = new ifstream(argv[argptr]); 1467 mol->CreateAdjacencyList2((ofstream *)&cout, input); 1468 input->close(); 1469 argptr+=1; 1470 } 1471 break; 1472 case 'N': 1473 ExitFlag = 1; 1474 if ((argptr+1 >= argc) || (argv[argptr+1][0] == '-')){ 1475 ExitFlag = 255; 1476 cerr << "Not enough or invalid arguments given for non-convex envelope: -o <radius> <tecplot output file>" << endl; 1477 } else { 1478 class Tesselation T; 1479 string filename(argv[argptr+1]); 1480 filename.append(".csv"); 1481 cout << Verbose(0) << "Evaluating non-convex envelope."; 1482 cout << Verbose(1) << "Using rolling ball of radius " << atof(argv[argptr]) << " and storing tecplot data in " << argv[argptr+1] << "." << endl; 1483 LinkedCell LCList(mol, atof(argv[argptr])*2.); 1484 Find_non_convex_border((ofstream *)&cout, mol, &T, &LCList, argv[argptr+1], atof(argv[argptr])); 1485 //FindDistributionOfEllipsoids((ofstream *)&cout, &T, &LCList, N, number, filename.c_str()); 1486 argptr+=2; 1487 } 1488 break; 1489 case 'S': 1490 ExitFlag = 1; 1491 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1492 ExitFlag = 255; 1493 cerr << "Not enough or invalid arguments given for storing tempature: -S <temperature file>" << endl; 1494 } else { 1495 cout << Verbose(1) << "Storing temperatures in " << argv[argptr] << "." << endl; 1496 ofstream *output = new ofstream(argv[argptr], ios::trunc); 1497 if (!mol->OutputTemperatureFromTrajectories((ofstream *)&cout, 0, mol->MDSteps, output)) 1498 cout << Verbose(2) << "File could not be written." << endl; 1499 else 1500 cout << Verbose(2) << "File stored." << endl; 1501 output->close(); 1502 delete(output); 1503 argptr+=1; 1504 } 1505 break; 1506 case 'P': 1507 ExitFlag = 1; 1508 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1509 ExitFlag = 255; 1510 cerr << "Not enough or invalid arguments given for parsing and integrating forces: -P <forces file>" << endl; 1511 } else { 1512 SaveFlag = true; 1513 cout << Verbose(1) << "Parsing forces file and Verlet integrating." << endl; 1514 if (!mol->VerletForceIntegration(argv[argptr], configuration.Deltat, configuration.GetIsAngstroem())) 1515 cout << Verbose(2) << "File not found." << endl; 1516 else 1517 cout << Verbose(2) << "File found and parsed." << endl; 1518 argptr+=1; 1519 } 1520 break; 1521 case 't': 1522 ExitFlag = 1; 1523 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) { 1524 ExitFlag = 255; 1525 cerr << "Not enough or invalid arguments given for translation: -t <x> <y> <z>" << endl; 1526 } else { 1527 ExitFlag = 1; 1528 SaveFlag = true; 1529 cout << Verbose(1) << "Translating all ions to new origin." << endl; 1530 for (int i=NDIM;i--;) 1531 x.x[i] = atof(argv[argptr+i]); 1532 mol->Translate((const Vector *)&x); 1533 argptr+=3; 1534 } 1535 break; 1536 1536 case 'T': 1537 1537 ExitFlag = 1; … … 1549 1549 } 1550 1550 break; 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 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1551 case 's': 1552 ExitFlag = 1; 1553 if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) { 1554 ExitFlag = 255; 1555 cerr << "Not enough or invalid arguments given for scaling: -s <factor/[factor_x]> [factor_y] [factor_z]" << endl; 1556 } else { 1557 SaveFlag = true; 1558 j = -1; 1559 cout << Verbose(1) << "Scaling all ion positions by factor." << endl; 1560 factor = new double[NDIM]; 1561 factor[0] = atof(argv[argptr]); 1562 if ((argptr < argc) && (IsValidNumber(argv[argptr]))) 1563 argptr++; 1564 factor[1] = atof(argv[argptr]); 1565 if ((argptr < argc) && (IsValidNumber(argv[argptr]))) 1566 argptr++; 1567 factor[2] = atof(argv[argptr]); 1568 mol->Scale(&factor); 1569 for (int i=0;i<NDIM;i++) { 1570 j += i+1; 1571 x.x[i] = atof(argv[NDIM+i]); 1572 mol->cell_size[j]*=factor[i]; 1573 } 1574 delete[](factor); 1575 argptr+=1; 1576 } 1577 break; 1578 case 'b': 1579 ExitFlag = 1; 1580 if ((argptr+5 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) || (!IsValidNumber(argv[argptr+3])) || (!IsValidNumber(argv[argptr+4])) || (!IsValidNumber(argv[argptr+5])) ) { 1581 ExitFlag = 255; 1582 cerr << "Not enough or invalid arguments given for centering in box: -b <xx> <xy> <xz> <yy> <yz> <zz>" << endl; 1583 } else { 1584 SaveFlag = true; 1585 cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl; 1586 for (int i=0;i<6;i++) { 1587 mol->cell_size[i] = atof(argv[argptr+i]); 1588 } 1589 // center 1590 mol->CenterInBox((ofstream *)&cout); 1591 1591 argptr+=6; 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1592 } 1593 break; 1594 case 'c': 1595 ExitFlag = 1; 1596 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) { 1597 ExitFlag = 255; 1598 cerr << "Not enough or invalid arguments given for centering with boundary: -c <boundary_x> <boundary_y> <boundary_z>" << endl; 1599 } else { 1600 SaveFlag = true; 1601 j = -1; 1602 cout << Verbose(1) << "Centering atoms in config file within given additional boundary." << endl; 1603 // make every coordinate positive 1604 mol->CenterEdge((ofstream *)&cout, &x); 1605 // update Box of atoms by boundary 1606 mol->SetBoxDimension(&x); 1607 // translate each coordinate by boundary 1608 j=-1; 1609 for (int i=0;i<NDIM;i++) { 1610 j += i+1; 1611 x.x[i] = atof(argv[argptr++]); 1612 mol->cell_size[j] += x.x[i]*2.; 1613 } 1614 mol->Translate((const Vector *)&x); 1615 1615 argptr+=3; 1616 1617 1618 1619 1620 1621 1622 1623 1616 } 1617 break; 1618 case 'O': 1619 ExitFlag = 1; 1620 SaveFlag = true; 1621 cout << Verbose(1) << "Centering atoms in origin." << endl; 1622 mol->CenterOrigin((ofstream *)&cout, &x); 1623 mol->SetBoxDimension(&x); 1624 1624 argptr+=0; 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 PrepareClustersinWater((ofstream *)&cout, &configuration, mol, volume, density);// if volume == 0, will calculate from ConvexEnvelope1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 mol->CountAtoms((ofstream *)&cout);// recount atoms1728 if (mol->AtomCount != 0) {// if there is more than none1729 count = mol->AtomCount;// is changed becausing of adding, thus has to be stored away beforehand1730 1731 1732 1733 1734 while (first->next != mol->end) {// make a list of all atoms with coordinates and element1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 for (int i=1;i<faktor;i++) {// then add this list with respective translation factor times1746 1747 1748 1749 first->x.CopyVector(vectors[k]);// use coordinate of original atom1750 first->x.AddVector(&x);// translate the coordinates1751 first->type = Elements[k];// insert original element1752 mol->AddAtom(first);// and add to the molecule (which increments ElementsInMolecule, AtomCount, ...)1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 default:// no match? Step on1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 } else {// no arguments, hence scan the elements db1781 1782 1783 1784 1785 1786 1787 1625 break; 1626 case 'r': 1627 ExitFlag = 1; 1628 SaveFlag = true; 1629 cout << Verbose(1) << "Converting config file from supposed old to new syntax." << endl; 1630 break; 1631 case 'F': 1632 case 'f': 1633 ExitFlag = 1; 1634 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1]))) { 1635 ExitFlag = 255; 1636 cerr << "Not enough or invalid arguments for fragmentation: -f <max. bond distance> <bond order>" << endl; 1637 } else { 1638 cout << "Fragmenting molecule with bond distance " << argv[argptr] << " angstroem, order of " << argv[argptr+1] << "." << endl; 1639 cout << Verbose(0) << "Creating connection matrix..." << endl; 1640 start = clock(); 1641 mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr++]), configuration.GetIsAngstroem()); 1642 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl; 1643 if (mol->first->next != mol->last) { 1644 ExitFlag = mol->FragmentMolecule((ofstream *)&cout, atoi(argv[argptr]), &configuration); 1645 } 1646 end = clock(); 1647 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl; 1648 argptr+=2; 1649 } 1650 break; 1651 case 'm': 1652 ExitFlag = 1; 1653 j = atoi(argv[argptr++]); 1654 if ((j<0) || (j>1)) { 1655 cerr << Verbose(1) << "ERROR: Argument of '-m' should be either 0 for no-rotate or 1 for rotate." << endl; 1656 j = 0; 1657 } 1658 if (j) { 1659 SaveFlag = true; 1660 cout << Verbose(0) << "Converting to prinicipal axis system." << endl; 1661 } else 1662 cout << Verbose(0) << "Evaluating prinicipal axis." << endl; 1663 mol->PrincipalAxisSystem((ofstream *)&cout, (bool)j); 1664 break; 1665 case 'o': 1666 ExitFlag = 1; 1667 if ((argptr >= argc) || (argv[argptr][0] == '-')){ 1668 ExitFlag = 255; 1669 cerr << "Not enough or invalid arguments given for convex envelope: -o <tecplot output file>" << endl; 1670 } else { 1671 cout << Verbose(0) << "Evaluating volume of the convex envelope."; 1672 cout << Verbose(1) << "Storing tecplot data in " << argv[argptr] << "." << endl; 1673 VolumeOfConvexEnvelope((ofstream *)&cout, argv[argptr], &configuration, NULL, mol); 1674 argptr+=1; 1675 } 1676 break; 1677 case 'U': 1678 ExitFlag = 1; 1679 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) ) { 1680 ExitFlag = 255; 1681 cerr << "Not enough or invalid arguments given for suspension with specified volume: -U <volume> <density>" << endl; 1682 volume = -1; // for case 'u': don't print error again 1683 } else { 1684 volume = atof(argv[argptr++]); 1685 cout << Verbose(0) << "Using " << volume << " angstrom^3 as the volume instead of convex envelope one's." << endl; 1686 } 1687 case 'u': 1688 ExitFlag = 1; 1689 if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) { 1690 if (volume != -1) 1691 ExitFlag = 255; 1692 cerr << "Not enough arguments given for suspension: -u <density>" << endl; 1693 } else { 1694 double density; 1695 SaveFlag = true; 1696 cout << Verbose(0) << "Evaluating necessary cell volume for a cluster suspended in water."; 1697 density = atof(argv[argptr++]); 1698 if (density < 1.0) { 1699 cerr << Verbose(0) << "Density must be greater than 1.0g/cm^3 !" << endl; 1700 density = 1.3; 1701 } 1702 // for(int i=0;i<NDIM;i++) { 1703 // repetition[i] = atoi(argv[argptr++]); 1704 // if (repetition[i] < 1) 1705 // cerr << Verbose(0) << "ERROR: repetition value must be greater 1!" << endl; 1706 // repetition[i] = 1; 1707 // } 1708 PrepareClustersinWater((ofstream *)&cout, &configuration, mol, volume, density); // if volume == 0, will calculate from ConvexEnvelope 1709 } 1710 break; 1711 case 'd': 1712 ExitFlag = 1; 1713 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) { 1714 ExitFlag = 255; 1715 cerr << "Not enough or invalid arguments given for repeating cells: -d <repeat_x> <repeat_y> <repeat_z>" << endl; 1716 } else { 1717 SaveFlag = true; 1718 for (int axis = 1; axis <= NDIM; axis++) { 1719 int faktor = atoi(argv[argptr++]); 1720 int count; 1721 element ** Elements; 1722 Vector ** vectors; 1723 if (faktor < 1) { 1724 cerr << Verbose(0) << "ERROR: Repetition faktor mus be greater than 1!" << endl; 1725 faktor = 1; 1726 } 1727 mol->CountAtoms((ofstream *)&cout); // recount atoms 1728 if (mol->AtomCount != 0) { // if there is more than none 1729 count = mol->AtomCount; // is changed becausing of adding, thus has to be stored away beforehand 1730 Elements = new element *[count]; 1731 vectors = new Vector *[count]; 1732 j = 0; 1733 first = mol->start; 1734 while (first->next != mol->end) { // make a list of all atoms with coordinates and element 1735 first = first->next; 1736 Elements[j] = first->type; 1737 vectors[j] = &first->x; 1738 j++; 1739 } 1740 if (count != j) 1741 cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl; 1742 x.Zero(); 1743 y.Zero(); 1744 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 1745 for (int i=1;i<faktor;i++) { // then add this list with respective translation factor times 1746 x.AddVector(&y); // per factor one cell width further 1747 for (int k=count;k--;) { // go through every atom of the original cell 1748 first = new atom(); // create a new body 1749 first->x.CopyVector(vectors[k]); // use coordinate of original atom 1750 first->x.AddVector(&x); // translate the coordinates 1751 first->type = Elements[k]; // insert original element 1752 mol->AddAtom(first); // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...) 1753 } 1754 } 1755 // free memory 1756 delete[](Elements); 1757 delete[](vectors); 1758 // correct cell size 1759 if (axis < 0) { // if sign was negative, we have to translate everything 1760 x.Zero(); 1761 x.AddVector(&y); 1762 x.Scale(-(faktor-1)); 1763 mol->Translate(&x); 1764 } 1765 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor; 1766 } 1767 } 1768 } 1769 break; 1770 default: // no match? Step on 1771 if ((argptr < argc) && (argv[argptr][0] != '-')) // if it started with a '-' we've already made a step! 1772 argptr++; 1773 break; 1774 } 1775 } 1776 } else argptr++; 1777 } while (argptr < argc); 1778 if (SaveFlag) 1779 SaveConfig(ConfigFileName, &configuration, periode, molecules); 1780 } else { // no arguments, hence scan the elements db 1781 if (periode->LoadPeriodentafel(configuration.databasepath)) 1782 cout << Verbose(0) << "Element list loaded successfully." << endl; 1783 else 1784 cout << Verbose(0) << "Element list loading failed." << endl; 1785 configuration.RetrieveConfigPathAndName("main_pcp_linux"); 1786 } 1787 return(ExitFlag); 1788 1788 }; 1789 1789 … … 1792 1792 int main(int argc, char **argv) 1793 1793 { 1794 1795 1796 1797 1798 char choice;// menu choice char1799 Vector x,y,z,n;// coordinates for absolute point in cell volume1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1794 periodentafel *periode = new periodentafel; // and a period table of all elements 1795 MoleculeListClass *molecules = new MoleculeListClass; // list of all molecules 1796 molecule *mol = NULL; 1797 config configuration; 1798 char choice; // menu choice char 1799 Vector x,y,z,n; // coordinates for absolute point in cell volume 1800 ifstream test; 1801 ofstream output; 1802 string line; 1803 char *ConfigFileName = NULL; 1804 int j, count; 1805 1806 // =========================== PARSE COMMAND LINE OPTIONS ==================================== 1807 j = ParseCommandLineOptions(argc, argv, molecules, periode, configuration, ConfigFileName); 1808 switch(j) { 1809 case 0: // something went wrong 1810 delete(molecules); // also free's all molecules contained 1811 delete(periode); 1812 return j; 1813 break; 1814 case 1: // just for -v and -h options 1815 delete(molecules); // also free's all molecules contained 1816 delete(periode); 1817 return 0; 1818 break; 1819 default: 1820 break; 1821 } 1822 1823 // General stuff 1824 if (molecules->ListOfMolecules.size() == 0) { 1825 1825 mol = new molecule(periode); 1826 1826 if (mol->cell_size[0] == 0.) { … … 1832 1832 } 1833 1833 molecules->insert(mol); 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1834 } 1835 1836 // =========================== START INTERACTIVE SESSION ==================================== 1837 1838 // now the main construction loop 1839 cout << Verbose(0) << endl << "Now comes the real construction..." << endl; 1840 do { 1841 cout << Verbose(0) << endl << endl; 1842 cout << Verbose(0) << "============Molecule list=======================" << endl; 1843 molecules->Enumerate((ofstream *)&cout); 1844 cout << Verbose(0) << "============Menu===============================" << endl; 1845 1845 cout << Verbose(0) << "a - set molecule (in)active" << endl; 1846 1846 cout << Verbose(0) << "e - edit new molecules" << endl; … … 1858 1858 cin >> choice; 1859 1859 1860 1861 1860 switch (choice) { 1861 case 'a': // (in)activate molecule 1862 1862 { 1863 1863 cout << "Enter index of molecule: "; … … 1869 1869 (*ListRunner)->ActiveFlag = !(*ListRunner)->ActiveFlag; 1870 1870 } 1871 1872 1873 1874 1875 1871 break; 1872 1873 case 'c': // edit each field of the configuration 1874 configuration.Edit(); 1875 break; 1876 1876 1877 1877 case 'e': // create molecule … … 1891 1891 break; 1892 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1893 case 'q': // quit 1894 break; 1895 1896 case 's': // save to config file 1897 SaveConfig(ConfigFileName, &configuration, periode, molecules); 1898 break; 1899 1900 case 'T': 1901 testroutine(molecules); 1902 break; 1903 1904 default: 1905 break; 1906 }; 1907 } while (choice != 'q'); 1908 1909 // save element data base 1910 if (periode->StorePeriodentafel(configuration.databasepath)) //ElementsFileName 1911 cout << Verbose(0) << "Saving of elements.db successful." << endl; 1912 else 1913 cout << Verbose(0) << "Saving of elements.db failed." << endl; 1914 1915 delete(molecules); // also free's all molecules contained 1916 delete(periode); 1917 return (0); 1918 1918 } 1919 1919 -
src/config.cpp
r205ccd r042f82 163 163 config::config() 164 164 { 165 166 167 165 mainname = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname"); 166 defaultpath = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: defaultpath"); 167 pseudopotpath = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: pseudopotpath"); 168 168 databasepath = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: databasepath"); 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 169 configpath = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: configpath"); 170 configname = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: configname"); 171 strcpy(mainname,"pcp"); 172 strcpy(defaultpath,"not specified"); 173 strcpy(pseudopotpath,"not specified"); 174 configpath[0]='\0'; 175 configname[0]='\0'; 176 basis = "3-21G"; 177 178 FastParsing = false; 179 ProcPEGamma=8; 180 ProcPEPsi=1; 181 DoOutVis=0; 182 DoOutMes=1; 183 DoOutNICS=0; 184 DoOutOrbitals=0; 185 DoOutCurrent=0; 186 DoPerturbation=0; 187 DoFullCurrent=0; 188 DoWannier=0; 189 CommonWannier=0; 190 SawtoothStart=0.01; 191 VectorPlane=0; 192 VectorCut=0; 193 UseAddGramSch=1; 194 Seed=1; 195 196 MaxOuterStep=0; 197 Deltat=1; 198 OutVisStep=10; 199 OutSrcStep=5; 200 TargetTemp=0.00095004455; 201 ScaleTempStep=25; 202 MaxPsiStep=0; 203 EpsWannier=1e-7; 204 205 MaxMinStep=100; 206 RelEpsTotalEnergy=1e-7; 207 RelEpsKineticEnergy=1e-5; 208 MaxMinStopStep=1; 209 MaxMinGapStopStep=0; 210 MaxInitMinStep=100; 211 InitRelEpsTotalEnergy=1e-5; 212 InitRelEpsKineticEnergy=1e-4; 213 InitMaxMinStopStep=1; 214 InitMaxMinGapStopStep=0; 215 216 //BoxLength[NDIM*NDIM]; 217 218 ECut=128.; 219 MaxLevel=5; 220 RiemannTensor=0; 221 LevRFactor=0; 222 RiemannLevel=0; 223 Lev0Factor=2; 224 RTActualUse=0; 225 PsiType=0; 226 MaxPsiDouble=0; 227 PsiMaxNoUp=0; 228 PsiMaxNoDown=0; 229 AddPsis=0; 230 231 RCut=20.; 232 StructOpt=0; 233 IsAngstroem=1; 234 RelativeCoord=0; 235 MaxTypes=0; 236 236 }; 237 237 … … 241 241 config::~config() 242 242 { 243 244 245 243 Free((void **)&mainname, "config::~config: *mainname"); 244 Free((void **)&defaultpath, "config::~config: *defaultpath"); 245 Free((void **)&pseudopotpath, "config::~config: *pseudopotpath"); 246 246 Free((void **)&databasepath, "config::~config: *databasepath"); 247 248 247 Free((void **)&configpath, "config::~config: *configpath"); 248 Free((void **)&configname, "config::~config: *configname"); 249 249 }; 250 250 … … 255 255 void config::Edit() 256 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 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 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 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 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 257 char choice; 258 259 do { 260 cout << Verbose(0) << "===========EDIT CONFIGURATION============================" << endl; 261 cout << Verbose(0) << " A - mainname (prefix for all runtime files)" << endl; 262 cout << Verbose(0) << " B - Default path (for runtime files)" << endl; 263 cout << Verbose(0) << " C - Path of pseudopotential files" << endl; 264 cout << Verbose(0) << " D - Number of coefficient sharing processes" << endl; 265 cout << Verbose(0) << " E - Number of wave function sharing processes" << endl; 266 cout << Verbose(0) << " F - 0: Don't output density for OpenDX, 1: do" << endl; 267 cout << Verbose(0) << " G - 0: Don't output physical data, 1: do" << endl; 268 cout << Verbose(0) << " H - 0: Don't output densities of each unperturbed orbital for OpenDX, 1: do" << endl; 269 cout << Verbose(0) << " I - 0: Don't output current density for OpenDX, 1: do" << endl; 270 cout << Verbose(0) << " J - 0: Don't do the full current calculation, 1: do" << endl; 271 cout << Verbose(0) << " K - 0: Don't do perturbation calculation to obtain susceptibility and shielding, 1: do" << endl; 272 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; 273 cout << Verbose(0) << " M - Absolute begin of unphysical sawtooth transfer for position operator within cell" << endl; 274 cout << Verbose(0) << " N - (0,1,2) x,y,z-plane to do two-dimensional current vector cut" << endl; 275 cout << Verbose(0) << " O - Absolute position along vector cut axis for cut plane" << endl; 276 cout << Verbose(0) << " P - Additional Gram-Schmidt-Orthonormalization to stabilize numerics" << endl; 277 cout << Verbose(0) << " Q - Initial integer value of random number generator" << endl; 278 cout << Verbose(0) << " R - for perturbation 0, for structure optimization defines upper limit of iterations" << endl; 279 cout << Verbose(0) << " T - Output visual after ...th step" << endl; 280 cout << Verbose(0) << " U - Output source densities of wave functions after ...th step" << endl; 281 cout << Verbose(0) << " X - minimization iterations per wave function, if unsure leave at default value 0" << endl; 282 cout << Verbose(0) << " Y - tolerance value for total spread in iterative Jacobi diagonalization" << endl; 283 cout << Verbose(0) << " Z - Maximum number of minimization iterations" << endl; 284 cout << Verbose(0) << " a - Relative change in total energy to stop min. iteration" << endl; 285 cout << Verbose(0) << " b - Relative change in kinetic energy to stop min. iteration" << endl; 286 cout << Verbose(0) << " c - Check stop conditions every ..th step during min. iteration" << endl; 287 cout << Verbose(0) << " e - Maximum number of minimization iterations during initial level" << endl; 288 cout << Verbose(0) << " f - Relative change in total energy to stop min. iteration during initial level" << endl; 289 cout << Verbose(0) << " g - Relative change in kinetic energy to stop min. iteration during initial level" << endl; 290 cout << Verbose(0) << " h - Check stop conditions every ..th step during min. iteration during initial level" << endl; 291 // cout << Verbose(0) << " j - six lower diagonal entries of matrix, defining the unit cell" << endl; 292 cout << Verbose(0) << " k - Energy cutoff of plane wave basis in Hartree" << endl; 293 cout << Verbose(0) << " l - Maximum number of levels in multi-level-ansatz" << endl; 294 cout << Verbose(0) << " m - Factor by which grid nodes increase between standard and upper level" << endl; 295 cout << Verbose(0) << " n - 0: Don't use RiemannTensor, 1: Do" << endl; 296 cout << Verbose(0) << " o - Factor by which grid nodes increase between Riemann and standard(?) level" << endl; 297 cout << Verbose(0) << " p - Number of Riemann levels" << endl; 298 cout << Verbose(0) << " r - 0: Don't Use RiemannTensor, 1: Do" << endl; 299 cout << Verbose(0) << " s - 0: Doubly occupied orbitals, 1: Up-/Down-Orbitals" << endl; 300 cout << Verbose(0) << " t - Number of orbitals (depends pn SpinType)" << endl; 301 cout << Verbose(0) << " u - Number of SpinUp orbitals (depends on SpinType)" << endl; 302 cout << Verbose(0) << " v - Number of SpinDown orbitals (depends on SpinType)" << endl; 303 cout << Verbose(0) << " w - Number of additional, unoccupied orbitals" << endl; 304 cout << Verbose(0) << " x - radial cutoff for ewald summation in Bohrradii" << endl; 305 cout << Verbose(0) << " y - 0: Don't do structure optimization beforehand, 1: Do" << endl; 306 cout << Verbose(0) << " z - 0: Units are in Bohr radii, 1: units are in Aengstrom" << endl; 307 cout << Verbose(0) << " i - 0: Coordinates given in file are absolute, 1: ... are relative to unit cell" << endl; 308 cout << Verbose(0) << "=========================================================" << endl; 309 cout << Verbose(0) << "INPUT: "; 310 cin >> choice; 311 312 switch (choice) { 313 case 'A': // mainname 314 cout << Verbose(0) << "Old: " << config::mainname << "\t new: "; 315 cin >> config::mainname; 316 break; 317 case 'B': // defaultpath 318 cout << Verbose(0) << "Old: " << config::defaultpath << "\t new: "; 319 cin >> config::defaultpath; 320 break; 321 case 'C': // pseudopotpath 322 cout << Verbose(0) << "Old: " << config::pseudopotpath << "\t new: "; 323 cin >> config::pseudopotpath; 324 break; 325 326 case 'D': // ProcPEGamma 327 cout << Verbose(0) << "Old: " << config::ProcPEGamma << "\t new: "; 328 cin >> config::ProcPEGamma; 329 break; 330 case 'E': // ProcPEPsi 331 cout << Verbose(0) << "Old: " << config::ProcPEPsi << "\t new: "; 332 cin >> config::ProcPEPsi; 333 break; 334 case 'F': // DoOutVis 335 cout << Verbose(0) << "Old: " << config::DoOutVis << "\t new: "; 336 cin >> config::DoOutVis; 337 break; 338 case 'G': // DoOutMes 339 cout << Verbose(0) << "Old: " << config::DoOutMes << "\t new: "; 340 cin >> config::DoOutMes; 341 break; 342 case 'H': // DoOutOrbitals 343 cout << Verbose(0) << "Old: " << config::DoOutOrbitals << "\t new: "; 344 cin >> config::DoOutOrbitals; 345 break; 346 case 'I': // DoOutCurrent 347 cout << Verbose(0) << "Old: " << config::DoOutCurrent << "\t new: "; 348 cin >> config::DoOutCurrent; 349 break; 350 case 'J': // DoFullCurrent 351 cout << Verbose(0) << "Old: " << config::DoFullCurrent << "\t new: "; 352 cin >> config::DoFullCurrent; 353 break; 354 case 'K': // DoPerturbation 355 cout << Verbose(0) << "Old: " << config::DoPerturbation << "\t new: "; 356 cin >> config::DoPerturbation; 357 break; 358 case 'L': // CommonWannier 359 cout << Verbose(0) << "Old: " << config::CommonWannier << "\t new: "; 360 cin >> config::CommonWannier; 361 break; 362 case 'M': // SawtoothStart 363 cout << Verbose(0) << "Old: " << config::SawtoothStart << "\t new: "; 364 cin >> config::SawtoothStart; 365 break; 366 case 'N': // VectorPlane 367 cout << Verbose(0) << "Old: " << config::VectorPlane << "\t new: "; 368 cin >> config::VectorPlane; 369 break; 370 case 'O': // VectorCut 371 cout << Verbose(0) << "Old: " << config::VectorCut << "\t new: "; 372 cin >> config::VectorCut; 373 break; 374 case 'P': // UseAddGramSch 375 cout << Verbose(0) << "Old: " << config::UseAddGramSch << "\t new: "; 376 cin >> config::UseAddGramSch; 377 break; 378 case 'Q': // Seed 379 cout << Verbose(0) << "Old: " << config::Seed << "\t new: "; 380 cin >> config::Seed; 381 break; 382 383 case 'R': // MaxOuterStep 384 cout << Verbose(0) << "Old: " << config::MaxOuterStep << "\t new: "; 385 cin >> config::MaxOuterStep; 386 break; 387 case 'T': // OutVisStep 388 cout << Verbose(0) << "Old: " << config::OutVisStep << "\t new: "; 389 cin >> config::OutVisStep; 390 break; 391 case 'U': // OutSrcStep 392 cout << Verbose(0) << "Old: " << config::OutSrcStep << "\t new: "; 393 cin >> config::OutSrcStep; 394 break; 395 case 'X': // MaxPsiStep 396 cout << Verbose(0) << "Old: " << config::MaxPsiStep << "\t new: "; 397 cin >> config::MaxPsiStep; 398 break; 399 case 'Y': // EpsWannier 400 cout << Verbose(0) << "Old: " << config::EpsWannier << "\t new: "; 401 cin >> config::EpsWannier; 402 break; 403 404 case 'Z': // MaxMinStep 405 cout << Verbose(0) << "Old: " << config::MaxMinStep << "\t new: "; 406 cin >> config::MaxMinStep; 407 break; 408 case 'a': // RelEpsTotalEnergy 409 cout << Verbose(0) << "Old: " << config::RelEpsTotalEnergy << "\t new: "; 410 cin >> config::RelEpsTotalEnergy; 411 break; 412 case 'b': // RelEpsKineticEnergy 413 cout << Verbose(0) << "Old: " << config::RelEpsKineticEnergy << "\t new: "; 414 cin >> config::RelEpsKineticEnergy; 415 break; 416 case 'c': // MaxMinStopStep 417 cout << Verbose(0) << "Old: " << config::MaxMinStopStep << "\t new: "; 418 cin >> config::MaxMinStopStep; 419 break; 420 case 'e': // MaxInitMinStep 421 cout << Verbose(0) << "Old: " << config::MaxInitMinStep << "\t new: "; 422 cin >> config::MaxInitMinStep; 423 break; 424 case 'f': // InitRelEpsTotalEnergy 425 cout << Verbose(0) << "Old: " << config::InitRelEpsTotalEnergy << "\t new: "; 426 cin >> config::InitRelEpsTotalEnergy; 427 break; 428 case 'g': // InitRelEpsKineticEnergy 429 cout << Verbose(0) << "Old: " << config::InitRelEpsKineticEnergy << "\t new: "; 430 cin >> config::InitRelEpsKineticEnergy; 431 break; 432 case 'h': // InitMaxMinStopStep 433 cout << Verbose(0) << "Old: " << config::InitMaxMinStopStep << "\t new: "; 434 cin >> config::InitMaxMinStopStep; 435 break; 436 437 // case 'j': // BoxLength 438 // cout << Verbose(0) << "enter lower triadiagonalo form of basis matrix" << endl << endl; 439 // for (int i=0;i<6;i++) { 440 // cout << Verbose(0) << "Cell size" << i << ": "; 441 // cin >> mol->cell_size[i]; 442 // } 443 // break; 444 445 case 'k': // ECut 446 cout << Verbose(0) << "Old: " << config::ECut << "\t new: "; 447 cin >> config::ECut; 448 break; 449 case 'l': // MaxLevel 450 cout << Verbose(0) << "Old: " << config::MaxLevel << "\t new: "; 451 cin >> config::MaxLevel; 452 break; 453 case 'm': // RiemannTensor 454 cout << Verbose(0) << "Old: " << config::RiemannTensor << "\t new: "; 455 cin >> config::RiemannTensor; 456 break; 457 case 'n': // LevRFactor 458 cout << Verbose(0) << "Old: " << config::LevRFactor << "\t new: "; 459 cin >> config::LevRFactor; 460 break; 461 case 'o': // RiemannLevel 462 cout << Verbose(0) << "Old: " << config::RiemannLevel << "\t new: "; 463 cin >> config::RiemannLevel; 464 break; 465 case 'p': // Lev0Factor 466 cout << Verbose(0) << "Old: " << config::Lev0Factor << "\t new: "; 467 cin >> config::Lev0Factor; 468 break; 469 case 'r': // RTActualUse 470 cout << Verbose(0) << "Old: " << config::RTActualUse << "\t new: "; 471 cin >> config::RTActualUse; 472 break; 473 case 's': // PsiType 474 cout << Verbose(0) << "Old: " << config::PsiType << "\t new: "; 475 cin >> config::PsiType; 476 break; 477 case 't': // MaxPsiDouble 478 cout << Verbose(0) << "Old: " << config::MaxPsiDouble << "\t new: "; 479 cin >> config::MaxPsiDouble; 480 break; 481 case 'u': // PsiMaxNoUp 482 cout << Verbose(0) << "Old: " << config::PsiMaxNoUp << "\t new: "; 483 cin >> config::PsiMaxNoUp; 484 break; 485 case 'v': // PsiMaxNoDown 486 cout << Verbose(0) << "Old: " << config::PsiMaxNoDown << "\t new: "; 487 cin >> config::PsiMaxNoDown; 488 break; 489 case 'w': // AddPsis 490 cout << Verbose(0) << "Old: " << config::AddPsis << "\t new: "; 491 cin >> config::AddPsis; 492 break; 493 494 case 'x': // RCut 495 cout << Verbose(0) << "Old: " << config::RCut << "\t new: "; 496 cin >> config::RCut; 497 break; 498 case 'y': // StructOpt 499 cout << Verbose(0) << "Old: " << config::StructOpt << "\t new: "; 500 cin >> config::StructOpt; 501 break; 502 case 'z': // IsAngstroem 503 cout << Verbose(0) << "Old: " << config::IsAngstroem << "\t new: "; 504 cin >> config::IsAngstroem; 505 break; 506 case 'i': // RelativeCoord 507 cout << Verbose(0) << "Old: " << config::RelativeCoord << "\t new: "; 508 cin >> config::RelativeCoord; 509 break; 510 }; 511 } while (choice != 'q'); 512 512 }; 513 513 … … 520 520 int config::TestSyntax(char *filename, periodentafel *periode, molecule *mol) 521 521 { 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 522 int test; 523 ifstream file(filename); 524 525 // search file for keyword: ProcPEGamma (new syntax) 526 if (ParseForParameter(1,&file,"ProcPEGamma", 0, 1, 1, int_type, &test, 1, optional)) { 527 file.close(); 528 return 1; 529 } 530 // search file for keyword: ProcsGammaPsi (old syntax) 531 if (ParseForParameter(1,&file,"ProcsGammaPsi", 0, 1, 1, int_type, &test, 1, optional)) { 532 file.close(); 533 return 0; 534 } 535 file.close(); 536 return -1; 537 537 } 538 538 … … 542 542 bool config::GetIsAngstroem() const 543 543 { 544 544 return (IsAngstroem == 1); 545 545 }; 546 546 … … 550 550 char * config::GetDefaultPath() const 551 551 { 552 552 return defaultpath; 553 553 }; 554 554 … … 559 559 void config::SetDefaultPath(const char *path) 560 560 { 561 561 strcpy(defaultpath, path); 562 562 }; 563 563 … … 567 567 void config::RetrieveConfigPathAndName(string filename) 568 568 { 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 569 char *ptr = NULL; 570 char *buffer = new char[MAXSTRINGSIZE]; 571 strncpy(buffer, filename.c_str(), MAXSTRINGSIZE); 572 int last = -1; 573 for(last=MAXSTRINGSIZE;last--;) { 574 if (buffer[last] == '/') 575 break; 576 } 577 if (last == -1) { // no path in front, set to local directory. 578 strcpy(configpath, "./"); 579 ptr = buffer; 580 } else { 581 strncpy(configpath, buffer, last+1); 582 ptr = &buffer[last+1]; 583 if (last < 254) 584 configpath[last+1]='\0'; 585 } 586 strcpy(configname, ptr); 587 cout << "Found configpath: " << configpath << ", dir slash was found at " << last << ", config name is " << configname << "." << endl; 588 delete[](buffer); 589 589 }; 590 590 … … 597 597 void config::Load(char *filename, periodentafel *periode, molecule *mol) 598 598 { 599 600 601 599 RetrieveConfigPathAndName(filename); 600 601 // ParseParameterFile 602 602 struct ConfigFileBuffer *FileBuffer = new ConfigFileBuffer(filename); 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 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 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 798 799 800 801 802 803 804 805 806 807 808 809 810 811 603 FileBuffer->InitMapping(); 604 605 /* Oeffne Hauptparameterdatei */ 606 int di; 607 double BoxLength[9]; 608 string zeile; 609 string dummy; 610 element *elementhash[MAX_ELEMENTS]; 611 char name[MAX_ELEMENTS]; 612 char keyword[MAX_ELEMENTS]; 613 int Z, No[MAX_ELEMENTS]; 614 int verbose = 0; 615 double value[3]; 616 617 /* Namen einlesen */ 618 619 ParseForParameter(verbose,FileBuffer, "mainname", 0, 1, 1, string_type, (config::mainname), 1, critical); 620 ParseForParameter(verbose,FileBuffer, "defaultpath", 0, 1, 1, string_type, (config::defaultpath), 1, critical); 621 ParseForParameter(verbose,FileBuffer, "pseudopotpath", 0, 1, 1, string_type, (config::pseudopotpath), 1, critical); 622 ParseForParameter(verbose,FileBuffer,"ProcPEGamma", 0, 1, 1, int_type, &(config::ProcPEGamma), 1, critical); 623 ParseForParameter(verbose,FileBuffer,"ProcPEPsi", 0, 1, 1, int_type, &(config::ProcPEPsi), 1, critical); 624 625 if (!ParseForParameter(verbose,FileBuffer,"Seed", 0, 1, 1, int_type, &(config::Seed), 1, optional)) 626 config::Seed = 1; 627 628 if(!ParseForParameter(verbose,FileBuffer,"DoOutOrbitals", 0, 1, 1, int_type, &(config::DoOutOrbitals), 1, optional)) { 629 config::DoOutOrbitals = 0; 630 } else { 631 if (config::DoOutOrbitals < 0) config::DoOutOrbitals = 0; 632 if (config::DoOutOrbitals > 1) config::DoOutOrbitals = 1; 633 } 634 ParseForParameter(verbose,FileBuffer,"DoOutVis", 0, 1, 1, int_type, &(config::DoOutVis), 1, critical); 635 if (config::DoOutVis < 0) config::DoOutVis = 0; 636 if (config::DoOutVis > 1) config::DoOutVis = 1; 637 if (!ParseForParameter(verbose,FileBuffer,"VectorPlane", 0, 1, 1, int_type, &(config::VectorPlane), 1, optional)) 638 config::VectorPlane = -1; 639 if (!ParseForParameter(verbose,FileBuffer,"VectorCut", 0, 1, 1, double_type, &(config::VectorCut), 1, optional)) 640 config::VectorCut = 0.; 641 ParseForParameter(verbose,FileBuffer,"DoOutMes", 0, 1, 1, int_type, &(config::DoOutMes), 1, critical); 642 if (config::DoOutMes < 0) config::DoOutMes = 0; 643 if (config::DoOutMes > 1) config::DoOutMes = 1; 644 if (!ParseForParameter(verbose,FileBuffer,"DoOutCurr", 0, 1, 1, int_type, &(config::DoOutCurrent), 1, optional)) 645 config::DoOutCurrent = 0; 646 if (config::DoOutCurrent < 0) config::DoOutCurrent = 0; 647 if (config::DoOutCurrent > 1) config::DoOutCurrent = 1; 648 ParseForParameter(verbose,FileBuffer,"AddGramSch", 0, 1, 1, int_type, &(config::UseAddGramSch), 1, critical); 649 if (config::UseAddGramSch < 0) config::UseAddGramSch = 0; 650 if (config::UseAddGramSch > 2) config::UseAddGramSch = 2; 651 if(!ParseForParameter(verbose,FileBuffer,"DoWannier", 0, 1, 1, int_type, &(config::DoWannier), 1, optional)) { 652 config::DoWannier = 0; 653 } else { 654 if (config::DoWannier < 0) config::DoWannier = 0; 655 if (config::DoWannier > 1) config::DoWannier = 1; 656 } 657 if(!ParseForParameter(verbose,FileBuffer,"CommonWannier", 0, 1, 1, int_type, &(config::CommonWannier), 1, optional)) { 658 config::CommonWannier = 0; 659 } else { 660 if (config::CommonWannier < 0) config::CommonWannier = 0; 661 if (config::CommonWannier > 4) config::CommonWannier = 4; 662 } 663 if(!ParseForParameter(verbose,FileBuffer,"SawtoothStart", 0, 1, 1, double_type, &(config::SawtoothStart), 1, optional)) { 664 config::SawtoothStart = 0.01; 665 } else { 666 if (config::SawtoothStart < 0.) config::SawtoothStart = 0.; 667 if (config::SawtoothStart > 1.) config::SawtoothStart = 1.; 668 } 669 670 ParseForParameter(verbose,FileBuffer,"MaxOuterStep", 0, 1, 1, int_type, &(config::MaxOuterStep), 1, critical); 671 if (!ParseForParameter(verbose,FileBuffer,"Deltat", 0, 1, 1, double_type, &(config::Deltat), 1, optional)) 672 config::Deltat = 1; 673 ParseForParameter(verbose,FileBuffer,"OutVisStep", 0, 1, 1, int_type, &(config::OutVisStep), 1, optional); 674 ParseForParameter(verbose,FileBuffer,"OutSrcStep", 0, 1, 1, int_type, &(config::OutSrcStep), 1, optional); 675 ParseForParameter(verbose,FileBuffer,"TargetTemp", 0, 1, 1, double_type, &(config::TargetTemp), 1, optional); 676 //ParseForParameter(verbose,FileBuffer,"Thermostat", 0, 1, 1, int_type, &(config::ScaleTempStep), 1, optional); 677 if (!ParseForParameter(verbose,FileBuffer,"EpsWannier", 0, 1, 1, double_type, &(config::EpsWannier), 1, optional)) 678 config::EpsWannier = 1e-8; 679 680 // stop conditions 681 //if (config::MaxOuterStep <= 0) config::MaxOuterStep = 1; 682 ParseForParameter(verbose,FileBuffer,"MaxPsiStep", 0, 1, 1, int_type, &(config::MaxPsiStep), 1, critical); 683 if (config::MaxPsiStep <= 0) config::MaxPsiStep = 3; 684 685 ParseForParameter(verbose,FileBuffer,"MaxMinStep", 0, 1, 1, int_type, &(config::MaxMinStep), 1, critical); 686 ParseForParameter(verbose,FileBuffer,"RelEpsTotalE", 0, 1, 1, double_type, &(config::RelEpsTotalEnergy), 1, critical); 687 ParseForParameter(verbose,FileBuffer,"RelEpsKineticE", 0, 1, 1, double_type, &(config::RelEpsKineticEnergy), 1, critical); 688 ParseForParameter(verbose,FileBuffer,"MaxMinStopStep", 0, 1, 1, int_type, &(config::MaxMinStopStep), 1, critical); 689 ParseForParameter(verbose,FileBuffer,"MaxMinGapStopStep", 0, 1, 1, int_type, &(config::MaxMinGapStopStep), 1, critical); 690 if (config::MaxMinStep <= 0) config::MaxMinStep = config::MaxPsiStep; 691 if (config::MaxMinStopStep < 1) config::MaxMinStopStep = 1; 692 if (config::MaxMinGapStopStep < 1) config::MaxMinGapStopStep = 1; 693 694 ParseForParameter(verbose,FileBuffer,"MaxInitMinStep", 0, 1, 1, int_type, &(config::MaxInitMinStep), 1, critical); 695 ParseForParameter(verbose,FileBuffer,"InitRelEpsTotalE", 0, 1, 1, double_type, &(config::InitRelEpsTotalEnergy), 1, critical); 696 ParseForParameter(verbose,FileBuffer,"InitRelEpsKineticE", 0, 1, 1, double_type, &(config::InitRelEpsKineticEnergy), 1, critical); 697 ParseForParameter(verbose,FileBuffer,"InitMaxMinStopStep", 0, 1, 1, int_type, &(config::InitMaxMinStopStep), 1, critical); 698 ParseForParameter(verbose,FileBuffer,"InitMaxMinGapStopStep", 0, 1, 1, int_type, &(config::InitMaxMinGapStopStep), 1, critical); 699 if (config::MaxInitMinStep <= 0) config::MaxInitMinStep = config::MaxPsiStep; 700 if (config::InitMaxMinStopStep < 1) config::InitMaxMinStopStep = 1; 701 if (config::InitMaxMinGapStopStep < 1) config::InitMaxMinGapStopStep = 1; 702 703 // Unit cell and magnetic field 704 ParseForParameter(verbose,FileBuffer, "BoxLength", 0, 3, 3, lower_trigrid, BoxLength, 1, critical); /* Lattice->RealBasis */ 705 mol->cell_size[0] = BoxLength[0]; 706 mol->cell_size[1] = BoxLength[3]; 707 mol->cell_size[2] = BoxLength[4]; 708 mol->cell_size[3] = BoxLength[6]; 709 mol->cell_size[4] = BoxLength[7]; 710 mol->cell_size[5] = BoxLength[8]; 711 //if (1) fprintf(stderr,"\n"); 712 713 ParseForParameter(verbose,FileBuffer,"DoPerturbation", 0, 1, 1, int_type, &(config::DoPerturbation), 1, optional); 714 ParseForParameter(verbose,FileBuffer,"DoOutNICS", 0, 1, 1, int_type, &(config::DoOutNICS), 1, optional); 715 if (!ParseForParameter(verbose,FileBuffer,"DoFullCurrent", 0, 1, 1, int_type, &(config::DoFullCurrent), 1, optional)) 716 config::DoFullCurrent = 0; 717 if (config::DoFullCurrent < 0) config::DoFullCurrent = 0; 718 if (config::DoFullCurrent > 2) config::DoFullCurrent = 2; 719 if (config::DoOutNICS < 0) config::DoOutNICS = 0; 720 if (config::DoOutNICS > 2) config::DoOutNICS = 2; 721 if (config::DoPerturbation == 0) { 722 config::DoFullCurrent = 0; 723 config::DoOutNICS = 0; 724 } 725 726 ParseForParameter(verbose,FileBuffer,"ECut", 0, 1, 1, double_type, &(config::ECut), 1, critical); 727 ParseForParameter(verbose,FileBuffer,"MaxLevel", 0, 1, 1, int_type, &(config::MaxLevel), 1, critical); 728 ParseForParameter(verbose,FileBuffer,"Level0Factor", 0, 1, 1, int_type, &(config::Lev0Factor), 1, critical); 729 if (config::Lev0Factor < 2) { 730 config::Lev0Factor = 2; 731 } 732 ParseForParameter(verbose,FileBuffer,"RiemannTensor", 0, 1, 1, int_type, &di, 1, critical); 733 if (di >= 0 && di < 2) { 734 config::RiemannTensor = di; 735 } else { 736 fprintf(stderr, "0 <= RiemanTensor < 2: 0 UseNotRT, 1 UseRT"); 737 exit(1); 738 } 739 switch (config::RiemannTensor) { 740 case 0: //UseNoRT 741 if (config::MaxLevel < 2) { 742 config::MaxLevel = 2; 743 } 744 config::LevRFactor = 2; 745 config::RTActualUse = 0; 746 break; 747 case 1: // UseRT 748 if (config::MaxLevel < 3) { 749 config::MaxLevel = 3; 750 } 751 ParseForParameter(verbose,FileBuffer,"RiemannLevel", 0, 1, 1, int_type, &(config::RiemannLevel), 1, critical); 752 if (config::RiemannLevel < 2) { 753 config::RiemannLevel = 2; 754 } 755 if (config::RiemannLevel > config::MaxLevel-1) { 756 config::RiemannLevel = config::MaxLevel-1; 757 } 758 ParseForParameter(verbose,FileBuffer,"LevRFactor", 0, 1, 1, int_type, &(config::LevRFactor), 1, critical); 759 if (config::LevRFactor < 2) { 760 config::LevRFactor = 2; 761 } 762 config::Lev0Factor = 2; 763 config::RTActualUse = 2; 764 break; 765 } 766 ParseForParameter(verbose,FileBuffer,"PsiType", 0, 1, 1, int_type, &di, 1, critical); 767 if (di >= 0 && di < 2) { 768 config::PsiType = di; 769 } else { 770 fprintf(stderr, "0 <= PsiType < 2: 0 UseSpinDouble, 1 UseSpinUpDown"); 771 exit(1); 772 } 773 switch (config::PsiType) { 774 case 0: // SpinDouble 775 ParseForParameter(verbose,FileBuffer,"MaxPsiDouble", 0, 1, 1, int_type, &(config::MaxPsiDouble), 1, critical); 776 ParseForParameter(verbose,FileBuffer,"AddPsis", 0, 1, 1, int_type, &(config::AddPsis), 1, optional); 777 break; 778 case 1: // SpinUpDown 779 if (config::ProcPEGamma % 2) config::ProcPEGamma*=2; 780 ParseForParameter(verbose,FileBuffer,"PsiMaxNoUp", 0, 1, 1, int_type, &(config::PsiMaxNoUp), 1, critical); 781 ParseForParameter(verbose,FileBuffer,"PsiMaxNoDown", 0, 1, 1, int_type, &(config::PsiMaxNoDown), 1, critical); 782 ParseForParameter(verbose,FileBuffer,"AddPsis", 0, 1, 1, int_type, &(config::AddPsis), 1, optional); 783 break; 784 } 785 786 // IonsInitRead 787 788 ParseForParameter(verbose,FileBuffer,"RCut", 0, 1, 1, double_type, &(config::RCut), 1, critical); 789 ParseForParameter(verbose,FileBuffer,"IsAngstroem", 0, 1, 1, int_type, &(config::IsAngstroem), 1, critical); 790 ParseForParameter(verbose,FileBuffer,"MaxTypes", 0, 1, 1, int_type, &(config::MaxTypes), 1, critical); 791 if (!ParseForParameter(verbose,FileBuffer,"RelativeCoord", 0, 1, 1, int_type, &(config::RelativeCoord) , 1, optional)) 792 config::RelativeCoord = 0; 793 if (!ParseForParameter(verbose,FileBuffer,"StructOpt", 0, 1, 1, int_type, &(config::StructOpt), 1, optional)) 794 config::StructOpt = 0; 795 if (MaxTypes == 0) { 796 cerr << "There are no atoms according to MaxTypes in this config file." << endl; 797 } else { 798 // prescan number of ions per type 799 cout << Verbose(0) << "Prescanning ions per type: " << endl; 800 int NoAtoms = 0; 801 for (int i=0; i < config::MaxTypes; i++) { 802 sprintf(name,"Ion_Type%i",i+1); 803 ParseForParameter(verbose,FileBuffer, (const char*)name, 0, 1, 1, int_type, &No[i], 1, critical); 804 ParseForParameter(verbose,FileBuffer, name, 0, 2, 1, int_type, &Z, 1, critical); 805 elementhash[i] = periode->FindElement(Z); 806 cout << Verbose(1) << i << ". Z = " << elementhash[i]->Z << " with " << No[i] << " ions." << endl; 807 NoAtoms += No[i]; 808 } 809 int repetition = 0; // which repeated keyword shall be read 810 811 // sort the lines via the LineMapping 812 812 sprintf(name,"Ion_Type%i",config::MaxTypes); 813 814 813 if (!ParseForParameter(verbose,FileBuffer, (const char*)name, 1, 1, 1, int_type, &value[0], 1, critical)) { 814 cerr << "There are no atoms in the config file!" << endl; 815 815 return; 816 816 } 817 818 819 820 821 //cout << FileBuffer->buffer[ FileBuffer->LineMapping[FileBuffer->CurrentLine+i]];822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 817 FileBuffer->CurrentLine++; 818 //cout << FileBuffer->buffer[ FileBuffer->LineMapping[FileBuffer->CurrentLine]]; 819 FileBuffer->MapIonTypesInBuffer(NoAtoms); 820 //for (int i=0; i<(NoAtoms < 100 ? NoAtoms : 100 < 100 ? NoAtoms : 100);++i) { 821 // cout << FileBuffer->buffer[ FileBuffer->LineMapping[FileBuffer->CurrentLine+i]]; 822 //} 823 824 map<int, atom *> AtomList[config::MaxTypes]; 825 map<int, atom *> LinearList; 826 if (!FastParsing) { 827 // parse in trajectories 828 bool status = true; 829 atom *neues = NULL; 830 while (status) { 831 cout << "Currently parsing MD step " << repetition << "." << endl; 832 for (int i=0; i < config::MaxTypes; i++) { 833 sprintf(name,"Ion_Type%i",i+1); 834 for(int j=0;j<No[i];j++) { 835 sprintf(keyword,"%s_%i",name, j+1); 836 if (repetition == 0) { 837 neues = new atom(); 838 AtomList[i][j] = neues; 839 LinearList[FileBuffer->CurrentLine] = neues; 840 neues->type = elementhash[i]; // find element type 841 } else 842 neues = AtomList[i][j]; 843 843 status = (status && 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 //cout << "Parsed position of step " << (repetition) << ": (";883 //for (int d=0;d<NDIM;d++)884 // cout << mol->Trajectories[neues].R.at(repetition).x[d] << " ";// next step885 //cout << ")\t(";886 //for (int d=0;d<NDIM;d++)887 // cout << mol->Trajectories[neues].U.at(repetition).x[d] << " ";// next step888 //cout << ")\t(";889 //for (int d=0;d<NDIM;d++)890 // cout << mol->Trajectories[neues].F.at(repetition).x[d] << " ";// next step891 //cout << ")" << endl;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 844 ParseForParameter(verbose,FileBuffer, keyword, 0, 1, 1, double_type, &neues->x.x[0], 1, (repetition == 0) ? critical : optional) && 845 ParseForParameter(verbose,FileBuffer, keyword, 0, 2, 1, double_type, &neues->x.x[1], 1, (repetition == 0) ? critical : optional) && 846 ParseForParameter(verbose,FileBuffer, keyword, 0, 3, 1, double_type, &neues->x.x[2], 1, (repetition == 0) ? critical : optional) && 847 ParseForParameter(verbose,FileBuffer, keyword, 0, 4, 1, int_type, &neues->FixedIon, 1, (repetition == 0) ? critical : optional)); 848 if (!status) break; 849 850 // check size of vectors 851 if (mol->Trajectories[neues].R.size() <= (unsigned int)(repetition)) { 852 //cout << "Increasing size for trajectory array of " << keyword << " to " << (repetition+10) << "." << endl; 853 mol->Trajectories[neues].R.resize(repetition+10); 854 mol->Trajectories[neues].U.resize(repetition+10); 855 mol->Trajectories[neues].F.resize(repetition+10); 856 } 857 858 // put into trajectories list 859 for (int d=0;d<NDIM;d++) 860 mol->Trajectories[neues].R.at(repetition).x[d] = neues->x.x[d]; 861 862 // parse velocities if present 863 if(!ParseForParameter(verbose,FileBuffer, keyword, 0, 5, 1, double_type, &neues->v.x[0], 1,optional)) 864 neues->v.x[0] = 0.; 865 if(!ParseForParameter(verbose,FileBuffer, keyword, 0, 6, 1, double_type, &neues->v.x[1], 1,optional)) 866 neues->v.x[1] = 0.; 867 if(!ParseForParameter(verbose,FileBuffer, keyword, 0, 7, 1, double_type, &neues->v.x[2], 1,optional)) 868 neues->v.x[2] = 0.; 869 for (int d=0;d<NDIM;d++) 870 mol->Trajectories[neues].U.at(repetition).x[d] = neues->v.x[d]; 871 872 // parse forces if present 873 if(!ParseForParameter(verbose,FileBuffer, keyword, 0, 8, 1, double_type, &value[0], 1,optional)) 874 value[0] = 0.; 875 if(!ParseForParameter(verbose,FileBuffer, keyword, 0, 9, 1, double_type, &value[1], 1,optional)) 876 value[1] = 0.; 877 if(!ParseForParameter(verbose,FileBuffer, keyword, 1, 10, 1, double_type, &value[2], 1,optional)) 878 value[2] = 0.; 879 for (int d=0;d<NDIM;d++) 880 mol->Trajectories[neues].F.at(repetition).x[d] = value[d]; 881 882 // cout << "Parsed position of step " << (repetition) << ": ("; 883 // for (int d=0;d<NDIM;d++) 884 // cout << mol->Trajectories[neues].R.at(repetition).x[d] << " "; // next step 885 // cout << ")\t("; 886 // for (int d=0;d<NDIM;d++) 887 // cout << mol->Trajectories[neues].U.at(repetition).x[d] << " "; // next step 888 // cout << ")\t("; 889 // for (int d=0;d<NDIM;d++) 890 // cout << mol->Trajectories[neues].F.at(repetition).x[d] << " "; // next step 891 // cout << ")" << endl; 892 } 893 } 894 repetition++; 895 } 896 // put atoms into the molecule in their original order 897 for(map<int, atom*>::iterator runner = LinearList.begin(); runner != LinearList.end(); ++runner) { 898 mol->AddAtom(runner->second); 899 } 900 repetition--; 901 cout << "Found " << repetition << " trajectory steps." << endl; 902 mol->MDSteps = repetition; 903 } else { 904 // 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) 905 repetition = 0; 906 while ( ParseForParameter(verbose,FileBuffer, "Ion_Type1_1", 0, 1, 1, double_type, &value[0], repetition, (repetition == 0) ? critical : optional) && 907 ParseForParameter(verbose,FileBuffer, "Ion_Type1_1", 0, 2, 1, double_type, &value[1], repetition, (repetition == 0) ? critical : optional) && 908 ParseForParameter(verbose,FileBuffer, "Ion_Type1_1", 0, 3, 1, double_type, &value[2], repetition, (repetition == 0) ? critical : optional)) 909 repetition++; 910 cout << "I found " << repetition << " times the keyword Ion_Type1_1." << endl; 911 // parse in molecule coordinates 912 for (int i=0; i < config::MaxTypes; i++) { 913 sprintf(name,"Ion_Type%i",i+1); 914 for(int j=0;j<No[i];j++) { 915 sprintf(keyword,"%s_%i",name, j+1); 916 atom *neues = new atom(); 917 // then parse for each atom the coordinates as often as present 918 ParseForParameter(verbose,FileBuffer, keyword, 0, 1, 1, double_type, &neues->x.x[0], repetition,critical); 919 ParseForParameter(verbose,FileBuffer, keyword, 0, 2, 1, double_type, &neues->x.x[1], repetition,critical); 920 ParseForParameter(verbose,FileBuffer, keyword, 0, 3, 1, double_type, &neues->x.x[2], repetition,critical); 921 ParseForParameter(verbose,FileBuffer, keyword, 0, 4, 1, int_type, &neues->FixedIon, repetition,critical); 922 if(!ParseForParameter(verbose,FileBuffer, keyword, 0, 5, 1, double_type, &neues->v.x[0], repetition,optional)) 923 neues->v.x[0] = 0.; 924 if(!ParseForParameter(verbose,FileBuffer, keyword, 0, 6, 1, double_type, &neues->v.x[1], repetition,optional)) 925 neues->v.x[1] = 0.; 926 if(!ParseForParameter(verbose,FileBuffer, keyword, 0, 7, 1, double_type, &neues->v.x[2], repetition,optional)) 927 neues->v.x[2] = 0.; 928 // here we don't care if forces are present (last in trajectories is always equal to current position) 929 neues->type = elementhash[i]; // find element type 930 mol->AddAtom(neues); 931 } 932 } 933 } 934 } 935 delete(FileBuffer); 936 936 }; 937 937 … … 943 943 void config::LoadOld(char *filename, periodentafel *periode, molecule *mol) 944 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 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 1064 1065 1066 1067 1068 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 input >> AtomNo;// number of atoms1112 input >> Z;// atomic number1113 1114 1115 1116 input >> b;// element mass1117 1118 cout << Verbose(1) << "AtomNo: " << AtomNo << "\tZ: " << Z << "\ta:" << a << "\tl:"<< l << "\b:" << b << "\tElement:" << elementhash[No] << "\t:" << endl;1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 945 ifstream *file = new ifstream(filename); 946 if (file == NULL) { 947 cerr << "ERROR: config file " << filename << " missing!" << endl; 948 return; 949 } 950 RetrieveConfigPathAndName(filename); 951 // ParseParameters 952 953 /* Oeffne Hauptparameterdatei */ 954 int l, i, di; 955 double a,b; 956 double BoxLength[9]; 957 string zeile; 958 string dummy; 959 element *elementhash[128]; 960 int Z, No, AtomNo, found; 961 int verbose = 0; 962 963 /* Namen einlesen */ 964 965 ParseForParameter(verbose,file, "mainname", 0, 1, 1, string_type, (config::mainname), 1, critical); 966 ParseForParameter(verbose,file, "defaultpath", 0, 1, 1, string_type, (config::defaultpath), 1, critical); 967 ParseForParameter(verbose,file, "pseudopotpath", 0, 1, 1, string_type, (config::pseudopotpath), 1, critical); 968 ParseForParameter(verbose,file, "ProcsGammaPsi", 0, 1, 1, int_type, &(config::ProcPEGamma), 1, critical); 969 ParseForParameter(verbose,file, "ProcsGammaPsi", 0, 2, 1, int_type, &(config::ProcPEPsi), 1, critical); 970 config::Seed = 1; 971 config::DoOutOrbitals = 0; 972 ParseForParameter(verbose,file,"DoOutVis", 0, 1, 1, int_type, &(config::DoOutVis), 1, critical); 973 if (config::DoOutVis < 0) config::DoOutVis = 0; 974 if (config::DoOutVis > 1) config::DoOutVis = 1; 975 config::VectorPlane = -1; 976 config::VectorCut = 0.; 977 ParseForParameter(verbose,file,"DoOutMes", 0, 1, 1, int_type, &(config::DoOutMes), 1, critical); 978 if (config::DoOutMes < 0) config::DoOutMes = 0; 979 if (config::DoOutMes > 1) config::DoOutMes = 1; 980 config::DoOutCurrent = 0; 981 ParseForParameter(verbose,file,"AddGramSch", 0, 1, 1, int_type, &(config::UseAddGramSch), 1, critical); 982 if (config::UseAddGramSch < 0) config::UseAddGramSch = 0; 983 if (config::UseAddGramSch > 2) config::UseAddGramSch = 2; 984 config::CommonWannier = 0; 985 config::SawtoothStart = 0.01; 986 987 ParseForParameter(verbose,file,"MaxOuterStep", 0, 1, 1, double_type, &(config::MaxOuterStep), 1, critical); 988 ParseForParameter(verbose,file,"Deltat", 0, 1, 1, double_type, &(config::Deltat), 1, optional); 989 ParseForParameter(verbose,file,"VisOuterStep", 0, 1, 1, int_type, &(config::OutVisStep), 1, optional); 990 ParseForParameter(verbose,file,"VisSrcOuterStep", 0, 1, 1, int_type, &(config::OutSrcStep), 1, optional); 991 ParseForParameter(verbose,file,"TargetTemp", 0, 1, 1, double_type, &(config::TargetTemp), 1, optional); 992 ParseForParameter(verbose,file,"ScaleTempStep", 0, 1, 1, int_type, &(config::ScaleTempStep), 1, optional); 993 config::EpsWannier = 1e-8; 994 995 // stop conditions 996 //if (config::MaxOuterStep <= 0) config::MaxOuterStep = 1; 997 ParseForParameter(verbose,file,"MaxPsiStep", 0, 1, 1, int_type, &(config::MaxPsiStep), 1, critical); 998 if (config::MaxPsiStep <= 0) config::MaxPsiStep = 3; 999 1000 ParseForParameter(verbose,file,"MaxMinStep", 0, 1, 1, int_type, &(config::MaxMinStep), 1, critical); 1001 ParseForParameter(verbose,file,"MaxMinStep", 0, 2, 1, double_type, &(config::RelEpsTotalEnergy), 1, critical); 1002 ParseForParameter(verbose,file,"MaxMinStep", 0, 3, 1, double_type, &(config::RelEpsKineticEnergy), 1, critical); 1003 ParseForParameter(verbose,file,"MaxMinStep", 0, 4, 1, int_type, &(config::MaxMinStopStep), 1, critical); 1004 if (config::MaxMinStep <= 0) config::MaxMinStep = config::MaxPsiStep; 1005 if (config::MaxMinStopStep < 1) config::MaxMinStopStep = 1; 1006 config::MaxMinGapStopStep = 1; 1007 1008 ParseForParameter(verbose,file,"MaxInitMinStep", 0, 1, 1, int_type, &(config::MaxInitMinStep), 1, critical); 1009 ParseForParameter(verbose,file,"MaxInitMinStep", 0, 2, 1, double_type, &(config::InitRelEpsTotalEnergy), 1, critical); 1010 ParseForParameter(verbose,file,"MaxInitMinStep", 0, 3, 1, double_type, &(config::InitRelEpsKineticEnergy), 1, critical); 1011 ParseForParameter(verbose,file,"MaxInitMinStep", 0, 4, 1, int_type, &(config::InitMaxMinStopStep), 1, critical); 1012 if (config::MaxInitMinStep <= 0) config::MaxInitMinStep = config::MaxPsiStep; 1013 if (config::InitMaxMinStopStep < 1) config::InitMaxMinStopStep = 1; 1014 config::InitMaxMinGapStopStep = 1; 1015 1016 ParseForParameter(verbose,file, "BoxLength", 0, 3, 3, lower_trigrid, BoxLength, 1, critical); /* Lattice->RealBasis */ 1017 mol->cell_size[0] = BoxLength[0]; 1018 mol->cell_size[1] = BoxLength[3]; 1019 mol->cell_size[2] = BoxLength[4]; 1020 mol->cell_size[3] = BoxLength[6]; 1021 mol->cell_size[4] = BoxLength[7]; 1022 mol->cell_size[5] = BoxLength[8]; 1023 if (1) fprintf(stderr,"\n"); 1024 config::DoPerturbation = 0; 1025 config::DoFullCurrent = 0; 1026 1027 ParseForParameter(verbose,file,"ECut", 0, 1, 1, double_type, &(config::ECut), 1, critical); 1028 ParseForParameter(verbose,file,"MaxLevel", 0, 1, 1, int_type, &(config::MaxLevel), 1, critical); 1029 ParseForParameter(verbose,file,"Level0Factor", 0, 1, 1, int_type, &(config::Lev0Factor), 1, critical); 1030 if (config::Lev0Factor < 2) { 1031 config::Lev0Factor = 2; 1032 } 1033 ParseForParameter(verbose,file,"RiemannTensor", 0, 1, 1, int_type, &di, 1, critical); 1034 if (di >= 0 && di < 2) { 1035 config::RiemannTensor = di; 1036 } else { 1037 fprintf(stderr, "0 <= RiemanTensor < 2: 0 UseNotRT, 1 UseRT"); 1038 exit(1); 1039 } 1040 switch (config::RiemannTensor) { 1041 case 0: //UseNoRT 1042 if (config::MaxLevel < 2) { 1043 config::MaxLevel = 2; 1044 } 1045 config::LevRFactor = 2; 1046 config::RTActualUse = 0; 1047 break; 1048 case 1: // UseRT 1049 if (config::MaxLevel < 3) { 1050 config::MaxLevel = 3; 1051 } 1052 ParseForParameter(verbose,file,"RiemannLevel", 0, 1, 1, int_type, &(config::RiemannLevel), 1, critical); 1053 if (config::RiemannLevel < 2) { 1054 config::RiemannLevel = 2; 1055 } 1056 if (config::RiemannLevel > config::MaxLevel-1) { 1057 config::RiemannLevel = config::MaxLevel-1; 1058 } 1059 ParseForParameter(verbose,file,"LevRFactor", 0, 1, 1, int_type, &(config::LevRFactor), 1, critical); 1060 if (config::LevRFactor < 2) { 1061 config::LevRFactor = 2; 1062 } 1063 config::Lev0Factor = 2; 1064 config::RTActualUse = 2; 1065 break; 1066 } 1067 ParseForParameter(verbose,file,"PsiType", 0, 1, 1, int_type, &di, 1, critical); 1068 if (di >= 0 && di < 2) { 1069 config::PsiType = di; 1070 } else { 1071 fprintf(stderr, "0 <= PsiType < 2: 0 UseSpinDouble, 1 UseSpinUpDown"); 1072 exit(1); 1073 } 1074 switch (config::PsiType) { 1075 case 0: // SpinDouble 1076 ParseForParameter(verbose,file,"MaxPsiDouble", 0, 1, 1, int_type, &(config::MaxPsiDouble), 1, critical); 1077 config::AddPsis = 0; 1078 break; 1079 case 1: // SpinUpDown 1080 if (config::ProcPEGamma % 2) config::ProcPEGamma*=2; 1081 ParseForParameter(verbose,file,"MaxPsiUp", 0, 1, 1, int_type, &(config::PsiMaxNoUp), 1, critical); 1082 ParseForParameter(verbose,file,"MaxPsiDown", 0, 1, 1, int_type, &(config::PsiMaxNoDown), 1, critical); 1083 config::AddPsis = 0; 1084 break; 1085 } 1086 1087 // IonsInitRead 1088 1089 ParseForParameter(verbose,file,"RCut", 0, 1, 1, double_type, &(config::RCut), 1, critical); 1090 ParseForParameter(verbose,file,"IsAngstroem", 0, 1, 1, int_type, &(config::IsAngstroem), 1, critical); 1091 config::RelativeCoord = 0; 1092 config::StructOpt = 0; 1093 1094 // Routine from builder.cpp 1095 1096 1097 for (i=MAX_ELEMENTS;i--;) 1098 elementhash[i] = NULL; 1099 cout << Verbose(0) << "Parsing Ions ..." << endl; 1100 No=0; 1101 found = 0; 1102 while (getline(*file,zeile,'\n')) { 1103 if (zeile.find("Ions_Data") == 0) { 1104 cout << Verbose(1) << "found Ions_Data...begin parsing" << endl; 1105 found ++; 1106 } 1107 if (found > 0) { 1108 if (zeile.find("Ions_Data") == 0) 1109 getline(*file,zeile,'\n'); // read next line and parse this one 1110 istringstream input(zeile); 1111 input >> AtomNo; // number of atoms 1112 input >> Z; // atomic number 1113 input >> a; 1114 input >> l; 1115 input >> l; 1116 input >> b; // element mass 1117 elementhash[No] = periode->FindElement(Z); 1118 cout << Verbose(1) << "AtomNo: " << AtomNo << "\tZ: " << Z << "\ta:" << a << "\tl:" << l << "\b:" << b << "\tElement:" << elementhash[No] << "\t:" << endl; 1119 for(i=0;i<AtomNo;i++) { 1120 if (!getline(*file,zeile,'\n')) {// parse on and on 1121 cout << Verbose(2) << "Error: Too few items in ionic list of element" << elementhash[No] << "." << endl << "Exiting." << endl; 1122 // return 1; 1123 } else { 1124 //cout << Verbose(2) << "Reading line: " << zeile << endl; 1125 } 1126 istringstream input2(zeile); 1127 atom *neues = new atom(); 1128 input2 >> neues->x.x[0]; // x 1129 input2 >> neues->x.x[1]; // y 1130 input2 >> neues->x.x[2]; // z 1131 input2 >> l; 1132 neues->type = elementhash[No]; // find element type 1133 mol->AddAtom(neues); 1134 } 1135 No++; 1136 } 1137 } 1138 file->close(); 1139 delete(file); 1140 1140 }; 1141 1141 … … 1147 1147 bool config::Save(const char *filename, periodentafel *periode, molecule *mol) const 1148 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 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 //switch (PsiType) {1220 //case 0:1221 1222 //break;1223 //case 1:1224 1225 1226 //break;1227 //}1228 1229 1230 1231 1232 1233 1234 *output << "MaxTypes\t" << mol->ElementCount <<"\t# maximum number of different ion types" << endl;1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1149 bool result = true; 1150 // bring MaxTypes up to date 1151 mol->CountElements(); 1152 ofstream *output = NULL; 1153 output = new ofstream(filename, ios::out); 1154 if (output != NULL) { 1155 *output << "# ParallelCarParinello - main configuration file - created with molecuilder" << endl; 1156 *output << endl; 1157 *output << "mainname\t" << config::mainname << "\t# programm name (for runtime files)" << endl; 1158 *output << "defaultpath\t" << config::defaultpath << "\t# where to put files during runtime" << endl; 1159 *output << "pseudopotpath\t" << config::pseudopotpath << "\t# where to find pseudopotentials" << endl; 1160 *output << endl; 1161 *output << "ProcPEGamma\t" << config::ProcPEGamma << "\t# for parallel computing: share constants" << endl; 1162 *output << "ProcPEPsi\t" << config::ProcPEPsi << "\t# for parallel computing: share wave functions" << endl; 1163 *output << "DoOutVis\t" << config::DoOutVis << "\t# Output data for OpenDX" << endl; 1164 *output << "DoOutMes\t" << config::DoOutMes << "\t# Output data for measurements" << endl; 1165 *output << "DoOutOrbitals\t" << config::DoOutOrbitals << "\t# Output all Orbitals" << endl; 1166 *output << "DoOutCurr\t" << config::DoOutCurrent << "\t# Ouput current density for OpenDx" << endl; 1167 *output << "DoOutNICS\t" << config::DoOutNICS << "\t# Output Nucleus independent current shieldings" << endl; 1168 *output << "DoPerturbation\t" << config::DoPerturbation << "\t# Do perturbation calculate and determine susceptibility and shielding" << endl; 1169 *output << "DoFullCurrent\t" << config::DoFullCurrent << "\t# Do full perturbation" << endl; 1170 *output << "CommonWannier\t" << config::CommonWannier << "\t# Put virtual centers at indivual orbits, all common, merged by variance, to grid point, to cell center" << endl; 1171 *output << "SawtoothStart\t" << config::SawtoothStart << "\t# Absolute value for smooth transition at cell border " << endl; 1172 *output << "VectorPlane\t" << config::VectorPlane << "\t# Cut plane axis (x, y or z: 0,1,2) for two-dim current vector plot" << endl; 1173 *output << "VectorCut\t" << config::VectorCut << "\t# Cut plane axis value" << endl; 1174 *output << "AddGramSch\t" << config::UseAddGramSch << "\t# Additional GramSchmidtOrtogonalization to be safe" << endl; 1175 *output << "Seed\t\t" << config::Seed << "\t# initial value for random seed for Psi coefficients" << endl; 1176 *output << endl; 1177 *output << "MaxOuterStep\t" << config::MaxOuterStep << "\t# number of MolecularDynamics/Structure optimization steps" << endl; 1178 *output << "Deltat\t" << config::Deltat << "\t# time per MD step" << endl; 1179 *output << "OutVisStep\t" << config::OutVisStep << "\t# Output visual data every ...th step" << endl; 1180 *output << "OutSrcStep\t" << config::OutSrcStep << "\t# Output \"restart\" data every ..th step" << endl; 1181 *output << "TargetTemp\t" << config::TargetTemp << "\t# Target temperature" << endl; 1182 *output << "MaxPsiStep\t" << config::MaxPsiStep << "\t# number of Minimisation steps per state (0 - default)" << endl; 1183 *output << "EpsWannier\t" << config::EpsWannier << "\t# tolerance value for spread minimisation of orbitals" << endl; 1184 *output << endl; 1185 *output << "# Values specifying when to stop" << endl; 1186 *output << "MaxMinStep\t" << config::MaxMinStep << "\t# Maximum number of steps" << endl; 1187 *output << "RelEpsTotalE\t" << config::RelEpsTotalEnergy << "\t# relative change in total energy" << endl; 1188 *output << "RelEpsKineticE\t" << config::RelEpsKineticEnergy << "\t# relative change in kinetic energy" << endl; 1189 *output << "MaxMinStopStep\t" << config::MaxMinStopStep << "\t# check every ..th steps" << endl; 1190 *output << "MaxMinGapStopStep\t" << config::MaxMinGapStopStep << "\t# check every ..th steps" << endl; 1191 *output << endl; 1192 *output << "# Values specifying when to stop for INIT, otherwise same as above" << endl; 1193 *output << "MaxInitMinStep\t" << config::MaxInitMinStep << "\t# Maximum number of steps" << endl; 1194 *output << "InitRelEpsTotalE\t" << config::InitRelEpsTotalEnergy << "\t# relative change in total energy" << endl; 1195 *output << "InitRelEpsKineticE\t" << config::InitRelEpsKineticEnergy << "\t# relative change in kinetic energy" << endl; 1196 *output << "InitMaxMinStopStep\t" << config::InitMaxMinStopStep << "\t# check every ..th steps" << endl; 1197 *output << "InitMaxMinGapStopStep\t" << config::InitMaxMinGapStopStep << "\t# check every ..th steps" << endl; 1198 *output << endl; 1199 *output << "BoxLength\t\t\t# (Length of a unit cell)" << endl; 1200 *output << mol->cell_size[0] << "\t" << endl; 1201 *output << mol->cell_size[1] << "\t" << mol->cell_size[2] << "\t" << endl; 1202 *output << mol->cell_size[3] << "\t" << mol->cell_size[4] << "\t" << mol->cell_size[5] << "\t" << endl; 1203 // FIXME 1204 *output << endl; 1205 *output << "ECut\t\t" << config::ECut << "\t# energy cutoff for discretization in Hartrees" << endl; 1206 *output << "MaxLevel\t" << config::MaxLevel << "\t# number of different levels in the code, >=2" << endl; 1207 *output << "Level0Factor\t" << config::Lev0Factor << "\t# factor by which node number increases from S to 0 level" << endl; 1208 *output << "RiemannTensor\t" << config::RiemannTensor << "\t# (Use metric)" << endl; 1209 switch (config::RiemannTensor) { 1210 case 0: //UseNoRT 1211 break; 1212 case 1: // UseRT 1213 *output << "RiemannLevel\t" << config::RiemannLevel << "\t# Number of Riemann Levels" << endl; 1214 *output << "LevRFactor\t" << config::LevRFactor << "\t# factor by which node number increases from 0 to R level from" << endl; 1215 break; 1216 } 1217 *output << "PsiType\t\t" << config::PsiType << "\t# 0 - doubly occupied, 1 - SpinUp,SpinDown" << endl; 1218 // write out both types for easier changing afterwards 1219 // switch (PsiType) { 1220 // case 0: 1221 *output << "MaxPsiDouble\t" << config::MaxPsiDouble << "\t# here: specifying both maximum number of SpinUp- and -Down-states" << endl; 1222 // break; 1223 // case 1: 1224 *output << "PsiMaxNoUp\t" << config::PsiMaxNoUp << "\t# here: specifying maximum number of SpinUp-states" << endl; 1225 *output << "PsiMaxNoDown\t" << config::PsiMaxNoDown << "\t# here: specifying maximum number of SpinDown-states" << endl; 1226 // break; 1227 // } 1228 *output << "AddPsis\t\t" << config::AddPsis << "\t# Additional unoccupied Psis for bandgap determination" << endl; 1229 *output << endl; 1230 *output << "RCut\t\t" << config::RCut << "\t# R-cut for the ewald summation" << endl; 1231 *output << "StructOpt\t" << config::StructOpt << "\t# Do structure optimization beforehand" << endl; 1232 *output << "IsAngstroem\t" << config::IsAngstroem << "\t# 0 - Bohr, 1 - Angstroem" << endl; 1233 *output << "RelativeCoord\t" << config::RelativeCoord << "\t# whether ion coordinates are relative (1) or absolute (0)" << endl; 1234 *output << "MaxTypes\t" << mol->ElementCount << "\t# maximum number of different ion types" << endl; 1235 *output << endl; 1236 result = result && mol->Checkout(output); 1237 if (mol->MDSteps <=1 ) 1238 result = result && mol->Output(output); 1239 else 1240 result = result && mol->OutputTrajectories(output); 1241 output->close(); 1242 output->clear(); 1243 delete(output); 1244 return result; 1245 } else 1246 return false; 1247 1247 }; 1248 1248 … … 1254 1254 bool config::SaveMPQC(const char *filename, molecule *mol) const 1255 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 1292 1293 1294 1295 1296 1297 1298 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 1256 int ElementNo = 0; 1257 int AtomNo; 1258 atom *Walker = NULL; 1259 element *runner = NULL; 1260 Vector *center = NULL; 1261 ofstream *output = NULL; 1262 stringstream *fname = NULL; 1263 1264 // first without hessian 1265 fname = new stringstream; 1266 *fname << filename << ".in"; 1267 output = new ofstream(fname->str().c_str(), ios::out); 1268 *output << "% Created by MoleCuilder" << endl; 1269 *output << "mpqc: (" << endl; 1270 *output << "\tsavestate = no" << endl; 1271 *output << "\tdo_gradient = yes" << endl; 1272 *output << "\tmole<MBPT2>: (" << endl; 1273 *output << "\t\tmaxiter = 200" << endl; 1274 *output << "\t\tbasis = $:basis" << endl; 1275 *output << "\t\tmolecule = $:molecule" << endl; 1276 *output << "\t\treference<CLHF>: (" << endl; 1277 *output << "\t\t\tbasis = $:basis" << endl; 1278 *output << "\t\t\tmolecule = $:molecule" << endl; 1279 *output << "\t\t)" << endl; 1280 *output << "\t)" << endl; 1281 *output << ")" << endl; 1282 *output << "molecule<Molecule>: (" << endl; 1283 *output << "\tunit = " << (IsAngstroem ? "angstrom" : "bohr" ) << endl; 1284 *output << "\t{ atoms geometry } = {" << endl; 1285 center = mol->DetermineCenterOfAll(output); 1286 // output of atoms 1287 runner = mol->elemente->start; 1288 while (runner->next != mol->elemente->end) { // go through every element 1289 runner = runner->next; 1290 if (mol->ElementsInMolecule[runner->Z]) { // if this element got atoms 1291 ElementNo++; 1292 AtomNo = 0; 1293 Walker = mol->start; 1294 while (Walker->next != mol->end) { // go through every atom of this element 1295 Walker = Walker->next; 1296 if (Walker->type == runner) { // if this atom fits to element 1297 AtomNo++; 1298 *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; 1299 } 1300 } 1301 } 1302 } 1303 delete(center); 1304 *output << "\t}" << endl; 1305 *output << ")" << endl; 1306 *output << "basis<GaussianBasisSet>: (" << endl; 1307 *output << "\tname = \""<< basis << "\"" << endl; 1308 *output << "\tmolecule = $:molecule" << endl; 1309 *output << ")" << endl; 1310 output->close(); 1311 delete(output); 1312 delete(fname); 1313 1314 // second with hessian 1315 fname = new stringstream; 1316 *fname << filename << ".hess.in"; 1317 output = new ofstream(fname->str().c_str(), ios::out); 1318 *output << "% Created by MoleCuilder" << endl; 1319 *output << "mpqc: (" << endl; 1320 *output << "\tsavestate = no" << endl; 1321 *output << "\tdo_gradient = yes" << endl; 1322 *output << "\tmole<CLHF>: (" << endl; 1323 *output << "\t\tmaxiter = 200" << endl; 1324 *output << "\t\tbasis = $:basis" << endl; 1325 *output << "\t\tmolecule = $:molecule" << endl; 1326 *output << "\t)" << endl; 1327 *output << "\tfreq<MolecularFrequencies>: (" << endl; 1328 *output << "\t\tmolecule=$:molecule" << endl; 1329 *output << "\t)" << endl; 1330 *output << ")" << endl; 1331 *output << "molecule<Molecule>: (" << endl; 1332 *output << "\tunit = " << (IsAngstroem ? "angstrom" : "bohr" ) << endl; 1333 *output << "\t{ atoms geometry } = {" << endl; 1334 center = mol->DetermineCenterOfAll(output); 1335 // output of atoms 1336 runner = mol->elemente->start; 1337 while (runner->next != mol->elemente->end) { // go through every element 1338 runner = runner->next; 1339 if (mol->ElementsInMolecule[runner->Z]) { // if this element got atoms 1340 ElementNo++; 1341 AtomNo = 0; 1342 Walker = mol->start; 1343 while (Walker->next != mol->end) { // go through every atom of this element 1344 Walker = Walker->next; 1345 if (Walker->type == runner) { // if this atom fits to element 1346 AtomNo++; 1347 *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; 1348 } 1349 } 1350 } 1351 } 1352 delete(center); 1353 *output << "\t}" << endl; 1354 *output << ")" << endl; 1355 *output << "basis<GaussianBasisSet>: (" << endl; 1356 *output << "\tname = \"3-21G\"" << endl; 1357 *output << "\tmolecule = $:molecule" << endl; 1358 *output << ")" << endl; 1359 output->close(); 1360 delete(output); 1361 delete(fname); 1362 1363 return true; 1364 1364 }; 1365 1365 … … 1373 1373 * \param name Name of value in file (at least 3 chars!) 1374 1374 * \param sequential 1 - do not reset file pointer to begin of file, 0 - set to beginning 1375 * 1376 * 1377 * 1375 * (if file is sequentially parsed this can be way faster! However, beware of multiple values per line, as whole line is read - 1376 * best approach: 0 0 0 1 (not resetted only on last value of line) - and of yth, which is now 1377 * counted from this unresetted position!) 1378 1378 * \param xth Which among a number of parameters it is (in grid case it's row number as grid is read as a whole!) 1379 1379 * \param yth In grid case specifying column number, otherwise the yth \a name matching line … … 1386 1386 */ 1387 1387 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) { 1388 int i,j;// loop variables1389 1390 1391 char *dummy1, *dummy, *free_dummy;// pointers in the line that is read in per step1392 1393 1394 1395 1396 1397 1398 1399 1400 int found = (type >= grid) ? 0 : (-yth + 1);// marks if yth parameter name was found1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 file->seekg(file_position, ios::beg);// rewind to start position1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 dummy = strchr(dummy1,'\t');// set dummy on first tab or space which ever's nearer1438 1439 dummy = strchr(dummy1, ' ');// if not found seek for space1440 while ((dummy != NULL) && ((*dummy == '\t') || (*dummy == ' ')))// skip some more tabs and spaces if necessary1441 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 file->seekg(file_position, ios::beg);// rewind to start position1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 while ((*dummy == '\t') || (*dummy == ' '))// skip interjacent tabs and spaces1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 dummy = strchr(dummy1, ' ');// if not found seek for space1511 1512 dummy = strchr(dummy1, '\n');// ... at line end then1513 if ((j < yth-1) && (type < 4)) {// check if xth value or not yet1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 file->seekg(file_position, ios::beg);// rewind to start position1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 file->seekg(file_position, ios::beg);// rewind to start position1536 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 strncpy((char *)value, dummy1, length);// copy as much1576 ((char *)value)[length] = '\0';// and set end marker1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 file->seekg(file_position, ios::beg);// rewind to start position1596 1597 1598 1599 1388 int i,j; // loop variables 1389 int length = 0, maxlength = -1; 1390 long file_position = file->tellg(); // mark current position 1391 char *dummy1, *dummy, *free_dummy; // pointers in the line that is read in per step 1392 dummy1 = free_dummy = (char *) Malloc(256 * sizeof(char), "config::ParseForParameter: *free_dummy"); 1393 1394 //fprintf(stderr,"Parsing for %s\n",name); 1395 if (repetition == 0) 1396 //Error(SomeError, "ParseForParameter(): argument repetition must not be 0!"); 1397 return 0; 1398 1399 int line = 0; // marks line where parameter was found 1400 int found = (type >= grid) ? 0 : (-yth + 1); // marks if yth parameter name was found 1401 while((found != repetition)) { 1402 dummy1 = dummy = free_dummy; 1403 do { 1404 file->getline(dummy1, 256); // Read the whole line 1405 if (file->eof()) { 1406 if ((critical) && (found == 0)) { 1407 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1408 //Error(InitReading, name); 1409 fprintf(stderr,"Error:InitReading, critical %s not found\n", name); 1410 exit(255); 1411 } else { 1412 //if (!sequential) 1413 file->clear(); 1414 file->seekg(file_position, ios::beg); // rewind to start position 1415 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1416 return 0; 1417 } 1418 } 1419 line++; 1420 } while (dummy != NULL && dummy1 != NULL && ((dummy1[0] == '#') || (dummy1[0] == '\0'))); // skip commentary and empty lines 1421 1422 // C++ getline removes newline at end, thus re-add 1423 if ((dummy1 != NULL) && (strchr(dummy1,'\n') == NULL)) { 1424 i = strlen(dummy1); 1425 dummy1[i] = '\n'; 1426 dummy1[i+1] = '\0'; 1427 } 1428 //fprintf(stderr,"line %i ends at %i, newline at %i\n", line, strlen(dummy1), strchr(dummy1,'\n')-free_dummy); 1429 1430 if (dummy1 == NULL) { 1431 if (verbose) fprintf(stderr,"Error reading line %i\n",line); 1432 } else { 1433 //fprintf(stderr,"Now parsing the line %i: %s\n", line, dummy1); 1434 } 1435 // Seek for possible end of keyword on line if given ... 1436 if (name != NULL) { 1437 dummy = strchr(dummy1,'\t'); // set dummy on first tab or space which ever's nearer 1438 if (dummy == NULL) { 1439 dummy = strchr(dummy1, ' '); // if not found seek for space 1440 while ((dummy != NULL) && ((*dummy == '\t') || (*dummy == ' '))) // skip some more tabs and spaces if necessary 1441 dummy++; 1442 } 1443 if (dummy == NULL) { 1444 dummy = strchr(dummy1, '\n'); // set on line end then (whole line = keyword) 1445 //fprintf(stderr,"Error: Cannot find tabs or spaces on line %i in search for %s\n", line, name); 1446 //Free((void **)&free_dummy); 1447 //Error(FileOpenParams, NULL); 1448 } else { 1449 //fprintf(stderr,"found tab at %i\n",(char *)dummy-(char *)dummy1); 1450 } 1451 } else dummy = dummy1; 1452 // ... and check if it is the keyword! 1453 //fprintf(stderr,"name %p, dummy %i/%c, dummy1 %i/%c, strlen(name) %i\n", &name, dummy, *dummy, dummy1, *dummy1, strlen(name)); 1454 if ((name == NULL) || (((dummy-dummy1 >= 3) && (strncmp(dummy1, name, strlen(name)) == 0)) && ((unsigned int)(dummy-dummy1) == strlen(name)))) { 1455 found++; // found the parameter! 1456 //fprintf(stderr,"found %s at line %i between %i and %i\n", name, line, dummy1, dummy); 1457 1458 if (found == repetition) { 1459 for (i=0;i<xth;i++) { // i = rows 1460 if (type >= grid) { 1461 // grid structure means that grid starts on the next line, not right after keyword 1462 dummy1 = dummy = free_dummy; 1463 do { 1464 file->getline(dummy1, 256); // Read the whole line, skip commentary and empty ones 1465 if (file->eof()) { 1466 if ((critical) && (found == 0)) { 1467 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1468 //Error(InitReading, name); 1469 fprintf(stderr,"Error:InitReading, critical %s not found\n", name); 1470 exit(255); 1471 } else { 1472 //if (!sequential) 1473 file->clear(); 1474 file->seekg(file_position, ios::beg); // rewind to start position 1475 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1476 return 0; 1477 } 1478 } 1479 line++; 1480 } while ((dummy1[0] == '#') || (dummy1[0] == '\n')); 1481 if (dummy1 == NULL){ 1482 if (verbose) fprintf(stderr,"Error reading line %i\n", line); 1483 } else { 1484 //fprintf(stderr,"Reading next line %i: %s\n", line, dummy1); 1485 } 1486 } else { // simple int, strings or doubles start in the same line 1487 while ((*dummy == '\t') || (*dummy == ' ')) // skip interjacent tabs and spaces 1488 dummy++; 1489 } 1490 // C++ getline removes newline at end, thus re-add 1491 if ((dummy1 != NULL) && (strchr(dummy1,'\n') == NULL)) { 1492 j = strlen(dummy1); 1493 dummy1[j] = '\n'; 1494 dummy1[j+1] = '\0'; 1495 } 1496 1497 int start = (type >= grid) ? 0 : yth-1 ; 1498 for (j=start;j<yth;j++) { // j = columns 1499 // check for lower triangular area and upper triangular area 1500 if ( ((i > j) && (type == upper_trigrid)) || ((j > i) && (type == lower_trigrid))) { 1501 *((double *)value) = 0.0; 1502 fprintf(stderr,"%f\t",*((double *)value)); 1503 value = (void *)((long)value + sizeof(double)); 1504 //value += sizeof(double); 1505 } else { 1506 // otherwise we must skip all interjacent tabs and spaces and find next value 1507 dummy1 = dummy; 1508 dummy = strchr(dummy1, '\t'); // seek for tab or space 1509 if (dummy == NULL) 1510 dummy = strchr(dummy1, ' '); // if not found seek for space 1511 if (dummy == NULL) { // if still zero returned ... 1512 dummy = strchr(dummy1, '\n'); // ... at line end then 1513 if ((j < yth-1) && (type < 4)) { // check if xth value or not yet 1514 if (critical) { 1515 if (verbose) fprintf(stderr,"Error: EoL at %i and still missing %i value(s) for parameter %s\n", line, yth-j, name); 1516 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1517 //return 0; 1518 exit(255); 1519 //Error(FileOpenParams, NULL); 1520 } else { 1521 //if (!sequential) 1522 file->clear(); 1523 file->seekg(file_position, ios::beg); // rewind to start position 1524 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1525 return 0; 1526 } 1527 } 1528 } else { 1529 //fprintf(stderr,"found tab at %i\n",(char *)dummy-(char *)free_dummy); 1530 } 1531 if (*dummy1 == '#') { 1532 // found comment, skipping rest of line 1533 //if (verbose) fprintf(stderr,"Error: '#' at %i and still missing %i value(s) for parameter %s\n", line, yth-j, name); 1534 if (!sequential) { // here we need it! 1535 file->seekg(file_position, ios::beg); // rewind to start position 1536 } 1537 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1538 return 0; 1539 } 1540 //fprintf(stderr,"value from %i to %i\n",(char *)dummy1-(char *)free_dummy,(char *)dummy-(char *)free_dummy); 1541 switch(type) { 1542 case (row_int): 1543 *((int *)value) = atoi(dummy1); 1544 if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name); 1545 if (verbose) fprintf(stderr,"%i\t",*((int *)value)); 1546 value = (void *)((long)value + sizeof(int)); 1547 //value += sizeof(int); 1548 break; 1549 case(row_double): 1550 case(grid): 1551 case(lower_trigrid): 1552 case(upper_trigrid): 1553 *((double *)value) = atof(dummy1); 1554 if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name); 1555 if (verbose) fprintf(stderr,"%lg\t",*((double *)value)); 1556 value = (void *)((long)value + sizeof(double)); 1557 //value += sizeof(double); 1558 break; 1559 case(double_type): 1560 *((double *)value) = atof(dummy1); 1561 if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %lg\n", name, *((double *) value)); 1562 //value += sizeof(double); 1563 break; 1564 case(int_type): 1565 *((int *)value) = atoi(dummy1); 1566 if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %i\n", name, *((int *) value)); 1567 //value += sizeof(int); 1568 break; 1569 default: 1570 case(string_type): 1571 if (value != NULL) { 1572 //if (maxlength == -1) maxlength = strlen((char *)value); // get maximum size of string array 1573 maxlength = MAXSTRINGSIZE; 1574 length = maxlength > (dummy-dummy1) ? (dummy-dummy1) : maxlength; // cap at maximum 1575 strncpy((char *)value, dummy1, length); // copy as much 1576 ((char *)value)[length] = '\0'; // and set end marker 1577 if ((verbose) && (i == xth-1)) fprintf(stderr,"%s is '%s' (%i chars)\n",name,((char *) value), length); 1578 //value += sizeof(char); 1579 } else { 1580 } 1581 break; 1582 } 1583 } 1584 while (*dummy == '\t') 1585 dummy++; 1586 } 1587 } 1588 } 1589 } 1590 } 1591 if ((type >= row_int) && (verbose)) fprintf(stderr,"\n"); 1592 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1593 if (!sequential) { 1594 file->clear(); 1595 file->seekg(file_position, ios::beg); // rewind to start position 1596 } 1597 //fprintf(stderr, "End of Parsing\n\n"); 1598 1599 return (found); // true if found, false if not 1600 1600 } 1601 1601 -
src/datacreator.cpp
r205ccd r042f82 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, const char *dir, const char *prefix, const char *msg, const 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, const char *dir, const char *prefix, const char *msg, const 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, const char *dir, const char *prefix,const char *msg, const 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, const char *dir, const char *prefix, const char *msg, const 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, const char *dir, const char *prefix, const char *msg, const 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, const char *dir, const char *prefix, const char *msg, const 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, const char *dir, const char *prefix, const char *msg, const 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, const char *dir, const char *prefix, const char *msg, const 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 const 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 const 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
r205ccd r042f82 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/element.cpp
r205ccd r042f82 12 12 */ 13 13 element::element() { 14 15 16 17 18 14 Z = -1; 15 No = -1; 16 previous = NULL; 17 next = NULL; 18 sort = NULL; 19 19 }; 20 20 … … 28 28 bool element::Output(ofstream *out) const 29 29 { 30 31 32 //*out << Z << "\t"<< fixed << setprecision(11) << showpoint << mass << "g/mol\t" << name << "\t" << symbol << "\t" << endl;33 34 35 30 if (out != NULL) { 31 *out << name << "\t" << symbol << "\t" << period << "\t" << group << "\t" << block << "\t" << Z << "\t" << mass << "\t" << CovalentRadius << "\t" << VanDerWaalsRadius << endl; 32 //*out << Z << "\t" << fixed << setprecision(11) << showpoint << mass << "g/mol\t" << name << "\t" << symbol << "\t" << endl; 33 return true; 34 } else 35 return false; 36 36 }; 37 37 38 38 /** Prints element data to \a *out. 39 39 * \param *out outstream 40 * \param No 40 * \param No cardinal number of element 41 41 * \param NoOfAtoms total number of atom of this element type 42 42 */ 43 43 bool element::Checkout(ofstream *out, const int Number, const int NoOfAtoms) const 44 44 { 45 46 47 48 49 45 if (out != NULL) { 46 *out << "Ion_Type" << Number << "\t" << NoOfAtoms << "\t" << Z << "\t1.0\t3\t3\t" << fixed << setprecision(11) << showpoint << mass << "\t" << name << "\t" << symbol <<endl; 47 return true; 48 } else 49 return false; 50 50 }; -
src/ellipsoid.cpp
r205ccd r042f82 2 2 * ellipsoid.cpp 3 3 * 4 * 5 * 4 * Created on: Jan 20, 2009 5 * Author: heber 6 6 */ 7 7 … … 17 17 double SquaredDistanceToEllipsoid(Vector &x, Vector &EllipsoidCenter, double *EllipsoidLength, double *EllipsoidAngle) 18 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 19 Vector helper, RefPoint; 20 double distance = -1.; 21 double Matrix[NDIM*NDIM]; 22 double InverseLength[3]; 23 double psi,theta,phi; // euler angles in ZX'Z'' convention 24 25 //cout << Verbose(3) << "Begin of SquaredDistanceToEllipsoid" << endl; 26 27 for(int i=0;i<3;i++) 28 InverseLength[i] = 1./EllipsoidLength[i]; 29 30 // 1. translate coordinate system so that ellipsoid center is in origin 31 helper.CopyVector(&x); 32 helper.SubtractVector(&EllipsoidCenter); 33 RefPoint.CopyVector(&helper); 34 //cout << Verbose(4) << "Translated given point is at " << RefPoint << "." << endl; 35 36 // 2. transform coordinate system by inverse of rotation matrix and of diagonal matrix 37 psi = EllipsoidAngle[0]; 38 theta = EllipsoidAngle[1]; 39 phi = EllipsoidAngle[2]; 40 Matrix[0] = cos(psi)*cos(phi) - sin(psi)*cos(theta)*sin(phi); 41 Matrix[1] = -cos(psi)*sin(phi) - sin(psi)*cos(theta)*cos(phi); 42 Matrix[2] = sin(psi)*sin(theta); 43 Matrix[3] = sin(psi)*cos(phi) + cos(psi)*cos(theta)*sin(phi); 44 Matrix[4] = cos(psi)*cos(theta)*cos(phi) - sin(psi)*sin(phi); 45 Matrix[5] = -cos(psi)*sin(theta); 46 Matrix[6] = sin(theta)*sin(phi); 47 Matrix[7] = sin(theta)*cos(phi); 48 Matrix[8] = cos(theta); 49 helper.MatrixMultiplication(Matrix); 50 helper.Scale(InverseLength); 51 //cout << Verbose(4) << "Transformed RefPoint is at " << helper << "." << endl; 52 53 // 3. construct intersection point with unit sphere and ray between origin and x 54 helper.Normalize(); // is simply normalizes vector in distance direction 55 //cout << Verbose(4) << "Transformed intersection is at " << helper << "." << endl; 56 57 // 4. transform back the constructed intersection point 58 psi = -EllipsoidAngle[0]; 59 theta = -EllipsoidAngle[1]; 60 phi = -EllipsoidAngle[2]; 61 helper.Scale(EllipsoidLength); 62 Matrix[0] = cos(psi)*cos(phi) - sin(psi)*cos(theta)*sin(phi); 63 Matrix[1] = -cos(psi)*sin(phi) - sin(psi)*cos(theta)*cos(phi); 64 Matrix[2] = sin(psi)*sin(theta); 65 Matrix[3] = sin(psi)*cos(phi) + cos(psi)*cos(theta)*sin(phi); 66 Matrix[4] = cos(psi)*cos(theta)*cos(phi) - sin(psi)*sin(phi); 67 Matrix[5] = -cos(psi)*sin(theta); 68 Matrix[6] = sin(theta)*sin(phi); 69 Matrix[7] = sin(theta)*cos(phi); 70 Matrix[8] = cos(theta); 71 helper.MatrixMultiplication(Matrix); 72 //cout << Verbose(4) << "Intersection is at " << helper << "." << endl; 73 74 // 5. determine distance between backtransformed point and x 75 distance = RefPoint.DistanceSquared(&helper); 76 //cout << Verbose(4) << "Squared distance between intersection and RefPoint is " << distance << "." << endl; 77 78 return distance; 79 //cout << Verbose(3) << "End of SquaredDistanceToEllipsoid" << endl; 80 80 }; 81 81 … … 83 83 */ 84 84 struct EllipsoidMinimisation { 85 int N;//!< dimension of vector set86 Vector *x;//!< array of vectors85 int N; //!< dimension of vector set 86 Vector *x; //!< array of vectors 87 87 }; 88 88 … … 94 94 double SumSquaredDistance (const gsl_vector * x, void * params) 95 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 96 Vector *set= ((struct EllipsoidMinimisation *)params)->x; 97 int N = ((struct EllipsoidMinimisation *)params)->N; 98 double SumDistance = 0.; 99 double distance; 100 Vector Center; 101 double EllipsoidLength[3], EllipsoidAngle[3]; 102 103 // put parameters into suitable ellipsoid form 104 for (int i=0;i<3;i++) { 105 Center.x[i] = gsl_vector_get(x, i+0); 106 EllipsoidLength[i] = gsl_vector_get(x, i+3); 107 EllipsoidAngle[i] = gsl_vector_get(x, i+6); 108 } 109 110 // go through all points and sum distance 111 for (int i=0;i<N;i++) { 112 distance = SquaredDistanceToEllipsoid(set[i], Center, EllipsoidLength, EllipsoidAngle); 113 if (!isnan(distance)) { 114 SumDistance += distance; 115 } else { 116 SumDistance = GSL_NAN; 117 break; 118 } 119 } 120 121 //cout << "Current summed distance is " << SumDistance << "." << endl; 122 return SumDistance; 123 123 }; 124 124 … … 132 132 bool FitPointSetToEllipsoid(ofstream *out, Vector *set, int N, Vector *EllipsoidCenter, double *EllipsoidLength, double *EllipsoidAngle) 133 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 134 int status = GSL_SUCCESS; 135 *out << Verbose(2) << "Begin of FitPointSetToEllipsoid " << endl; 136 if (N >= 3) { // check that enough points are given (9 d.o.f.) 137 struct EllipsoidMinimisation par; 138 const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex; 139 gsl_multimin_fminimizer *s = NULL; 140 gsl_vector *ss, *x; 141 gsl_multimin_function minex_func; 142 143 size_t iter = 0; 144 double size; 145 146 /* Starting point */ 147 x = gsl_vector_alloc (9); 148 for (int i=0;i<3;i++) { 149 gsl_vector_set (x, i+0, EllipsoidCenter->x[i]); 150 gsl_vector_set (x, i+3, EllipsoidLength[i]); 151 gsl_vector_set (x, i+6, EllipsoidAngle[i]); 152 } 153 par.x = set; 154 par.N = N; 155 156 /* Set initial step sizes */ 157 ss = gsl_vector_alloc (9); 158 for (int i=0;i<3;i++) { 159 gsl_vector_set (ss, i+0, 0.1); 160 gsl_vector_set (ss, i+3, 1.0); 161 gsl_vector_set (ss, i+6, M_PI/20.); 162 } 163 164 /* Initialize method and iterate */ 165 minex_func.n = 9; 166 minex_func.f = &SumSquaredDistance; 167 minex_func.params = (void *)∥ 168 169 s = gsl_multimin_fminimizer_alloc (T, 9); 170 gsl_multimin_fminimizer_set (s, &minex_func, x, ss); 171 172 do { 173 iter++; 174 status = gsl_multimin_fminimizer_iterate(s); 175 176 if (status) 177 break; 178 179 size = gsl_multimin_fminimizer_size (s); 180 status = gsl_multimin_test_size (size, 1e-2); 181 182 if (status == GSL_SUCCESS) { 183 for (int i=0;i<3;i++) { 184 EllipsoidCenter->x[i] = gsl_vector_get (s->x,i+0); 185 EllipsoidLength[i] = gsl_vector_get (s->x, i+3); 186 EllipsoidAngle[i] = gsl_vector_get (s->x, i+6); 187 } 188 *out << setprecision(3) << Verbose(4) << "Converged fit at: " << *EllipsoidCenter << ", lengths " << EllipsoidLength[0] << ", " << EllipsoidLength[1] << ", " << EllipsoidLength[2] << ", angles " << EllipsoidAngle[0] << ", " << EllipsoidAngle[1] << ", " << EllipsoidAngle[2] << " with summed distance " << s->fval << "." << endl; 189 } 190 191 } while (status == GSL_CONTINUE && iter < 1000); 192 193 gsl_vector_free(x); 194 gsl_vector_free(ss); 195 gsl_multimin_fminimizer_free (s); 196 197 } else { 198 *out << Verbose(3) << "Not enough points provided for fit to ellipsoid." << endl; 199 return false; 200 } 201 *out << Verbose(2) << "End of FitPointSetToEllipsoid" << endl; 202 if (status == GSL_SUCCESS) 203 return true; 204 else 205 return false; 206 206 }; 207 207 … … 217 217 size_t PointsLeft = 0; 218 218 size_t PointsPicked = 0; 219 220 set<int> PickedAtomNrs;// ordered list of picked atoms221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 if (List == NULL) {// set index to it241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 if (PointsLeft < PointsToPick) {// ensure that we can pick enough points in its neighbourhood at all.263 264 265 266 267 268 269 270 current = PickedAtomNrs.find(index);// not present?271 272 273 274 275 276 277 278 279 280 281 282 283 284 // 285 286 // 287 // 288 // 289 // 290 291 292 293 294 x[PointsPicked++].CopyVector(&(Candidate->x));// we have one more atom picked295 current++;// next pre-picked atom296 297 index++;// next atom nr.298 299 // 300 // 301 302 303 304 305 306 if (PointsPicked == PointsToPick)// break out of loop if we have all307 308 309 310 219 int Nlower[NDIM], Nupper[NDIM]; 220 set<int> PickedAtomNrs; // ordered list of picked atoms 221 set<int>::iterator current; 222 int index; 223 atom *Candidate = NULL; 224 LinkedAtoms *List = NULL; 225 *out << Verbose(2) << "Begin of PickRandomPointSet" << endl; 226 227 // allocate array 228 if (x == NULL) { 229 x = new Vector[PointsToPick]; 230 } else { 231 *out << "WARNING: Given pointer to vector array seems already allocated." << endl; 232 } 233 234 do { 235 for(int i=0;i<NDIM;i++) // pick three random indices 236 LC->n[i] = (rand() % LC->N[i]); 237 *out << Verbose(2) << "INFO: Center cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " ... "; 238 // get random cell 239 List = LC->GetCurrentCell(); 240 if (List == NULL) { // set index to it 241 continue; 242 } 243 *out << "with No. " << LC->index << "." << endl; 244 245 *out << Verbose(2) << "LC Intervals:"; 246 for (int i=0;i<NDIM;i++) { 247 Nlower[i] = ((LC->n[i]-1) >= 0) ? LC->n[i]-1 : 0; 248 Nupper[i] = ((LC->n[i]+1) < LC->N[i]) ? LC->n[i]+1 : LC->N[i]-1; 249 *out << " [" << Nlower[i] << "," << Nupper[i] << "] "; 250 } 251 *out << endl; 252 253 // count whether there are sufficient atoms in this cell+neighbors 254 PointsLeft=0; 255 for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++) 256 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++) 257 for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) { 258 List = LC->GetCurrentCell(); 259 PointsLeft += List->size(); 260 } 261 *out << Verbose(2) << "There are " << PointsLeft << " atoms in this neighbourhood." << endl; 262 if (PointsLeft < PointsToPick) { // ensure that we can pick enough points in its neighbourhood at all. 263 continue; 264 } 265 266 // pre-pick a fixed number of atoms 267 PickedAtomNrs.clear(); 268 do { 269 index = (rand() % PointsLeft); 270 current = PickedAtomNrs.find(index); // not present? 271 if (current == PickedAtomNrs.end()) { 272 //*out << Verbose(2) << "Picking atom nr. " << index << "." << endl; 273 PickedAtomNrs.insert(index); 274 } 275 } while (PickedAtomNrs.size() < PointsToPick); 276 277 index = 0; // now go through all and pick those whose from PickedAtomsNr 278 PointsPicked=0; 279 current = PickedAtomNrs.begin(); 280 for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++) 281 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++) 282 for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) { 283 List = LC->GetCurrentCell(); 284 // *out << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << " containing " << List->size() << " points." << endl; 285 if (List != NULL) { 286 // if (List->begin() != List->end()) 287 // *out << Verbose(2) << "Going through candidates ... " << endl; 288 // else 289 // *out << Verbose(2) << "Cell is empty ... " << endl; 290 for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) { 291 if ((current != PickedAtomNrs.end()) && (*current == index)) { 292 Candidate = (*Runner); 293 *out << Verbose(2) << "Current picked node is " << **Runner << " with index " << index << "." << endl; 294 x[PointsPicked++].CopyVector(&(Candidate->x)); // we have one more atom picked 295 current++; // next pre-picked atom 296 } 297 index++; // next atom nr. 298 } 299 // } else { 300 // *out << Verbose(2) << "List for this index not allocated!" << endl; 301 } 302 } 303 *out << Verbose(2) << "The following points were picked: " << endl; 304 for (size_t i=0;i<PointsPicked;i++) 305 *out << Verbose(2) << x[i] << endl; 306 if (PointsPicked == PointsToPick) // break out of loop if we have all 307 break; 308 } while(1); 309 310 *out << Verbose(2) << "End of PickRandomPointSet" << endl; 311 311 }; 312 312 … … 321 321 size_t PointsLeft = (size_t) T->PointsOnBoundaryCount; 322 322 size_t PointsPicked = 0; 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 323 double value, threshold; 324 PointMap *List = &T->PointsOnBoundary; 325 *out << Verbose(2) << "Begin of PickRandomPointSet" << endl; 326 327 // allocate array 328 if (x == NULL) { 329 x = new Vector[PointsToPick]; 330 } else { 331 *out << "WARNING: Given pointer to vector array seems already allocated." << endl; 332 } 333 334 if (List != NULL) 335 for (PointMap::iterator Runner = List->begin(); Runner != List->end(); Runner++) { 336 threshold = 1. - (double)(PointsToPick - PointsPicked)/(double)PointsLeft; 337 value = (double)rand()/(double)RAND_MAX; 338 //*out << Verbose(3) << "Current node is " << *Runner->second->node << " with " << value << " ... " << threshold << ": "; 339 if (value > threshold) { 340 x[PointsPicked].CopyVector(&(Runner->second->node->x)); 341 PointsPicked++; 342 //*out << "IN." << endl; 343 } else { 344 //*out << "OUT." << endl; 345 } 346 PointsLeft--; 347 } 348 *out << Verbose(2) << "The following points were picked: " << endl; 349 for (size_t i=0;i<PointsPicked;i++) 350 *out << Verbose(3) << x[i] << endl; 351 352 *out << Verbose(2) << "End of PickRandomPointSet" << endl; 353 353 }; 354 354 … … 363 363 void FindDistributionOfEllipsoids(ofstream *out, class Tesselation *T, class LinkedCell *LCList, int N, int number, const char *filename) 364 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 393 394 395 396 397 398 399 400 401 402 403 404 EllipsoidCenter.CopyVector(&Center);// use Center of Gravity as initial center of ellipsoid405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 delete[](x);// free allocated memory for point set428 429 430 431 432 433 }; 365 ofstream output; 366 Vector *x = NULL; 367 Vector Center; 368 Vector EllipsoidCenter; 369 double EllipsoidLength[3]; 370 double EllipsoidAngle[3]; 371 double distance, MaxDistance, MinDistance; 372 *out << Verbose(0) << "Begin of FindDistributionOfEllipsoids" << endl; 373 374 // construct center of gravity of boundary point set for initial ellipsoid center 375 Center.Zero(); 376 for (PointMap::iterator Runner = T->PointsOnBoundary.begin(); Runner != T->PointsOnBoundary.end(); Runner++) 377 Center.AddVector(&Runner->second->node->x); 378 Center.Scale(1./T->PointsOnBoundaryCount); 379 *out << Verbose(1) << "Center is at " << Center << "." << endl; 380 381 // Output header 382 output.open(filename, ios::trunc); 383 output << "# Nr.\tCenterX\tCenterY\tCenterZ\ta\tb\tc\tpsi\ttheta\tphi" << endl; 384 385 // loop over desired number of parameter sets 386 for (;number >0;number--) { 387 *out << Verbose(1) << "Determining data set " << number << " ... " << endl; 388 // pick the point set 389 x = NULL; 390 //PickRandomPointSet(out, T, LCList, x, N); 391 PickRandomNeighbouredPointSet(out, T, LCList, x, N); 392 393 // calculate some sensible starting values for parameter fit 394 MaxDistance = 0.; 395 MinDistance = x[0].ScalarProduct(&x[0]); 396 for (int i=0;i<N;i++) { 397 distance = x[i].ScalarProduct(&x[i]); 398 if (distance > MaxDistance) 399 MaxDistance = distance; 400 if (distance < MinDistance) 401 MinDistance = distance; 402 } 403 //*out << Verbose(2) << "MinDistance " << MinDistance << ", MaxDistance " << MaxDistance << "." << endl; 404 EllipsoidCenter.CopyVector(&Center); // use Center of Gravity as initial center of ellipsoid 405 for (int i=0;i<3;i++) 406 EllipsoidAngle[i] = 0.; 407 EllipsoidLength[0] = sqrt(MaxDistance); 408 EllipsoidLength[1] = sqrt((MaxDistance+MinDistance)/2.); 409 EllipsoidLength[2] = sqrt(MinDistance); 410 411 // fit the parameters 412 if (FitPointSetToEllipsoid(out, x, N, &EllipsoidCenter, &EllipsoidLength[0], &EllipsoidAngle[0])) { 413 *out << Verbose(1) << "Picking succeeded!" << endl; 414 // output obtained parameter set 415 output << number << "\t"; 416 for (int i=0;i<3;i++) 417 output << setprecision(9) << EllipsoidCenter.x[i] << "\t"; 418 for (int i=0;i<3;i++) 419 output << setprecision(9) << EllipsoidLength[i] << "\t"; 420 for (int i=0;i<3;i++) 421 output << setprecision(9) << EllipsoidAngle[i] << "\t"; 422 output << endl; 423 } else { // increase N to pick one more 424 *out << Verbose(1) << "Picking failed!" << endl; 425 number++; 426 } 427 delete[](x); // free allocated memory for point set 428 } 429 // close output and finish 430 output.close(); 431 432 *out << Verbose(0) << "End of FindDistributionOfEllipsoids" << endl; 433 }; -
src/ellipsoid.hpp
r205ccd r042f82 2 2 * ellipsoid.hpp 3 3 * 4 * 5 * 4 * Created on: Jan 20, 2009 5 * Author: heber 6 6 */ 7 7 -
src/helpers.cpp
r205ccd r042f82 15 15 double ask_value(const char *text) 16 16 { 17 18 19 20 21 22 17 double test = 0.1439851348959832147598734598273456723948652983045928346598365; 18 do { 19 cout << Verbose(0) << text; 20 cin >> test; 21 } while (test == 0.1439851348959832147598734598273456723948652983045928346598365); 22 return test; 23 23 }; 24 24 … … 29 29 #ifdef HAVE_DEBUG 30 30 void debug_in(const char *output, const char *file, const int line) { 31 31 if (output) fprintf(stderr,"DEBUG: in %s at line %i: %s\n", file, line, output); 32 32 } 33 33 #else 34 void debug_in(const char *output, const char *file, const int line) {} 34 void debug_in(const char *output, const char *file, const int line) {} // print nothing 35 35 #endif 36 36 … … 42 42 void * Malloc(size_t size, const char* output) 43 43 { 44 45 46 47 48 44 void *buffer = NULL; 45 buffer = (void *)malloc(size); // alloc 46 if (buffer == NULL) 47 cout << Verbose(0) << "Malloc failed - pointer is NULL: " << output << endl; 48 return(buffer); 49 49 }; 50 50 … … 56 56 void * Calloc(size_t size, const char* output) 57 57 { 58 59 60 61 62 58 void *buffer = NULL; 59 buffer = (void *)calloc(size, (size_t)0); // alloc 60 if (buffer == NULL) 61 cout << Verbose(0) << "Calloc failed - pointer is NULL: " << output << endl; 62 return(buffer); 63 63 }; 64 64 … … 71 71 void * ReAlloc(void * OldPointer, size_t size, const char* output) 72 72 { 73 74 75 76 77 78 79 80 81 73 void *buffer = NULL; 74 if (OldPointer == NULL) 75 //cout << Verbose(0) << "ReAlloc impossible - old is NULL: " << output << endl; 76 buffer = (void *)malloc(size); // malloc 77 else 78 buffer = (void *)realloc(OldPointer, size); // realloc 79 if (buffer == NULL) 80 cout << Verbose(0) << "ReAlloc failed - new is NULL: " << output << endl; 81 return(buffer); 82 82 }; 83 83 … … 88 88 void Free(void ** buffer, const char* output) 89 89 { 90 91 92 93 94 95 90 if (*buffer == NULL) { 91 //cout << Verbose(5) << "Free not necesary: " << output << endl; 92 } else { 93 free(*buffer); 94 *buffer = NULL; 95 } 96 96 }; 97 97 … … 103 103 char* MallocString(size_t size, const char* output) 104 104 { 105 106 107 108 109 110 for (i=size;i--;)// reset111 112 113 105 size_t i; 106 char *buffer; 107 buffer = (char *)malloc(sizeof(char) * (size+1)); // alloc 108 if (buffer == NULL) 109 cout << Verbose(0) << output << endl; 110 for (i=size;i--;) // reset 111 buffer[i] = i % 2 == 0 ? 'p': 'c'; 112 buffer[size] = '\0'; // and set length marker on its end 113 return(buffer); 114 114 } 115 115 … … 121 121 void bound(double *b, double lower_bound, double upper_bound) 122 122 { 123 124 125 126 127 123 double step = (upper_bound - lower_bound); 124 while (*b >= upper_bound) 125 *b -= step; 126 while (*b < lower_bound) 127 *b += step; 128 128 }; 129 129 … … 134 134 void flip(double *x, double *y) 135 135 { 136 137 138 139 136 double tmp; 137 tmp = *x; 138 *x = *y; 139 *y = tmp; 140 140 }; 141 141 … … 147 147 int pot(int base, int n) 148 148 { 149 150 151 152 153 149 int res = 1; 150 int j; 151 for (j=n;j--;) 152 res *= base; 153 return res; 154 154 }; 155 155 … … 161 161 char *FixedDigitNumber(const int FragmentNumber, const int digits) 162 162 { 163 164 165 166 167 168 169 170 171 172 173 // terminateand fill string array from end backward174 175 176 177 178 179 180 181 163 char *returnstring; 164 int number = FragmentNumber; 165 int order = 0; 166 while (number != 0) { // determine number of digits needed 167 number = (int)floor(((double)number / 10.)); 168 order++; 169 //cout << "Number is " << number << ", order is " << order << "." << endl; 170 } 171 // allocate string 172 returnstring = (char *) Malloc(sizeof(char)*(order+2), "FixedDigitNumber: *returnstring"); 173 // terminate and fill string array from end backward 174 returnstring[order] = '\0'; 175 number = digits; 176 for (int i=order;i--;) { 177 returnstring[i] = '0' + (char)(number % 10); 178 number = (int)floor(((double)number / 10.)); 179 } 180 //cout << returnstring << endl; 181 return returnstring; 182 182 }; 183 183 … … 188 188 bool IsValidNumber( const char *string) 189 189 { 190 191 192 193 194 195 190 int ptr = 0; 191 if ((string[ptr] == '.') || (string[ptr] == '-')) // number may be negative or start with dot 192 ptr++; 193 if ((string[ptr] >= '0') && (string[ptr] <= '9')) 194 return true; 195 return false; 196 196 }; 197 197 -
src/helpers.hpp
r205ccd r042f82 38 38 39 39 /* Behandelt aufgetretene Fehler. error ist der Fehlertyp(enum Errors) 40 41 40 void *SpecialData ist ein untypisierter Zeiger auf Spezielle Daten zur Fehlerbehandlung. 41 Man koennte auch noch einen Zeiger auf eine Funktion uebergeben */ 42 42 extern void /*@exits@*/ debug(const char *output); 43 43 //__attribute__ ((__return__)); 44 44 #define debug(data) debug_in((data), __FILE__, __LINE__) 45 45 46 46 extern void /*@exits@*/ debug_in(const char *output, 47 48 47 const char *file, const int line); 48 //__attribute__ ((__return__)); 49 49 50 50 double ask_value(const char *text); … … 73 73 template <typename T> bool CreateFatherLookupTable(ofstream *out, T *start, T *end, T **&LookupTable, int count = 0) 74 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 75 bool status = true; 76 T *Walker = NULL; 77 int AtomNo; 78 79 if (LookupTable != NULL) { 80 *out << "Pointer for Lookup table is not NULL! Aborting ..." <<endl; 81 return false; 82 } 83 84 // count them 85 if (count == 0) { 86 Walker = start; 87 while (Walker->next != end) { // create a lookup table (Atom::nr -> atom) used as a marker table lateron 88 Walker = Walker->next; 89 count = (count < Walker->GetTrueFather()->nr) ? Walker->GetTrueFather()->nr : count; 90 } 91 } 92 if (count <= 0) { 93 *out << "Count of lookup list is 0 or less." << endl; 94 return false; 95 } 96 97 // allocat and fill 98 LookupTable = (T **) Malloc(sizeof(T *)*count, "CreateFatherLookupTable - **LookupTable"); 99 if (LookupTable == NULL) { 100 cerr << "LookupTable memory allocation failed!" << endl; 101 status = false; 102 } else { 103 for (int i=0;i<count;i++) 104 LookupTable[i] = NULL; 105 Walker = start; 106 while (Walker->next != end) { // create a lookup table (Atom::nr -> atom) used as a marker table lateron 107 Walker = Walker->next; 108 AtomNo = Walker->GetTrueFather()->nr; 109 if ((AtomNo >= 0) && (AtomNo < count)) { 110 //*out << "Setting LookupTable[" << AtomNo << "] to " << *Walker << endl; 111 LookupTable[AtomNo] = Walker; 112 } else { 113 *out << "Walker " << *Walker << " exceeded range of nuclear ids [0, " << count << ")." << endl; 114 status = false; 115 break; 116 } 117 } 118 } 119 120 return status; 121 121 }; 122 122 … … 129 129 template <typename X> void link(X *walker, X *end) 130 130 { 131 132 133 134 135 136 131 X *vorher = end->previous; 132 if (vorher != NULL) 133 vorher->next = walker; 134 end->previous = walker; 135 walker->previous = vorher; 136 walker->next = end; 137 137 }; 138 138 … … 143 143 template <typename X> void unlink(X *walker) 144 144 { 145 146 147 148 145 if (walker->next != NULL) 146 walker->next->previous = walker->previous; 147 if (walker->previous != NULL) 148 walker->previous->next = walker->next; 149 149 }; 150 150 151 151 /** Adds new item before an item \a *end in a list. 152 * \param *pointer 153 * \param *end 152 * \param *pointer item to be added 153 * \param *end end of list 154 154 * \return true - addition succeeded, false - unable to add item to list 155 155 */ 156 template <typename X> 157 { 158 159 160 161 162 163 164 156 template <typename X> bool add(X *pointer, X *end) 157 { 158 if (end != NULL) { 159 link(pointer, end); 160 } else { 161 pointer->previous = NULL; 162 pointer->next = NULL; 163 } 164 return true; 165 165 }; 166 166 167 167 /** Finds item in list 168 * \param *suche 169 * \param *start 170 * \param *end 168 * \param *suche search criteria 169 * \param *start begin of list 170 * \param *end end of list 171 171 * \return X - if found, NULL - if not found 172 172 */ 173 173 template <typename X, typename Y> X * find(Y *suche, X *start, X *end) 174 174 { 175 176 177 178 179 180 175 X *walker = start; 176 while (walker->next != end) { // go through list 177 walker = walker->next; // step onward beforehand 178 if (*walker->sort == *suche) return (walker); 179 } 180 return NULL; 181 181 }; 182 182 … … 187 187 template <typename X> void removewithoutcheck(X *walker) 188 188 { 189 190 191 192 193 189 if (walker != NULL) { 190 unlink(walker); 191 delete(walker); 192 walker = NULL; 193 } 194 194 }; 195 195 196 196 /** Removes an item from the list, checks if exists. 197 197 * Checks beforehand if atom is really within molecule list. 198 * \param *pointer 199 * \param *start 200 * \param *end 198 * \param *pointer item to be removed 199 * \param *start begin of list 200 * \param *end end of list 201 201 * \return true - removing succeeded, false - given item not found in list 202 202 */ 203 203 template <typename X> bool remove(X *pointer, X *start, X *end) 204 204 { 205 206 /* 207 208 if (walker == end) return false;// item not found in list209 210 211 212 213 214 215 205 X *walker = find (pointer->sort, start, end); 206 /* while (walker->next != pointer) { // search through list 207 walker = walker->next; 208 if (walker == end) return false; // item not found in list 209 }*/ 210 // atom found, now unlink 211 if (walker != NULL) 212 removewithoutcheck(walker); 213 else 214 return false; 215 return true; 216 216 }; 217 217 … … 223 223 template <typename X> bool cleanup(X *start, X *end) 224 224 { 225 226 227 228 229 230 231 232 233 234 235 225 X *pointer = start->next; 226 X *walker; 227 while (pointer != end) { // go through list 228 walker = pointer; // mark current 229 pointer = pointer->next; // step onward beforehand 230 // remove walker 231 unlink(walker); 232 delete(walker); 233 walker = NULL; 234 } 235 return true; 236 236 }; 237 237 … … 242 242 template <typename X> X *GetFirst(X *me) 243 243 { 244 245 246 247 244 X *Binder = me; 245 while(Binder->previous != NULL) 246 Binder = Binder->previous; 247 return Binder; 248 248 }; 249 249 … … 254 254 template <typename X> X *GetLast(X *me) 255 255 { 256 257 258 259 256 X *Binder = me; 257 while(Binder->next != NULL) 258 Binder = Binder->next; 259 return Binder; 260 260 }; 261 261 … … 266 266 template <typename X> void Free2DArray(X **ptr, int dim) 267 267 { 268 269 270 271 272 273 274 268 int i; 269 if (ptr != NULL) { 270 for(i=dim;i--;) 271 if (ptr[i] != NULL) 272 free(ptr[i]); 273 free(ptr); 274 } 275 275 }; 276 276 … … 281 281 class Verbose 282 282 { 283 284 285 286 287 288 283 public: 284 Verbose(int value) : Verbosity(value) { } 285 286 ostream& print (ostream &ost) const; 287 private: 288 int Verbosity; 289 289 }; 290 290 … … 295 295 class Binary 296 296 { 297 298 299 300 301 302 297 public: 298 Binary(int value) : BinaryNumber(value) { } 299 300 ostream& print (ostream &ost) const; 301 private: 302 int BinaryNumber; 303 303 }; 304 304 -
src/joiner.cpp
r205ccd r042f82 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/linkedcell.cpp
r205ccd r042f82 6 6 LinkedCell::LinkedCell() 7 7 { 8 9 10 11 12 13 14 8 LC = NULL; 9 for(int i=0;i<NDIM;i++) 10 N[i] = 0; 11 index = -1; 12 RADIUS = 0.; 13 max.Zero(); 14 min.Zero(); 15 15 }; 16 16 … … 21 21 LinkedCell::LinkedCell(molecule *mol, double radius) 22 22 { 23 23 atom *Walker = NULL; 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 25 RADIUS = radius; 26 LC = NULL; 27 for(int i=0;i<NDIM;i++) 28 N[i] = 0; 29 index = -1; 30 max.Zero(); 31 min.Zero(); 32 cout << Verbose(1) << "Begin of LinkedCell" << endl; 33 if (mol->start->next == mol->end) { 34 cerr << "ERROR: molecule contains no atoms!" << endl; 35 return; 36 } 37 // 1. find max and min per axis of atoms 38 Walker = mol->start->next; 39 for (int i=0;i<NDIM;i++) { 40 max.x[i] = Walker->x.x[i]; 41 min.x[i] = Walker->x.x[i]; 42 } 43 while (Walker != mol->end) { 44 for (int i=0;i<NDIM;i++) { 45 if (max.x[i] < Walker->x.x[i]) 46 max.x[i] = Walker->x.x[i]; 47 if (min.x[i] > Walker->x.x[i]) 48 min.x[i] = Walker->x.x[i]; 49 } 50 Walker = Walker->next; 51 } 52 cout << Verbose(2) << "Bounding box is " << min << " and " << max << "." << endl; 53 53 54 55 56 57 58 54 // 2. find then umber of cells per axis 55 for (int i=0;i<NDIM;i++) { 56 N[i] = (int)floor((max.x[i] - min.x[i])/RADIUS)+1; 57 } 58 cout << Verbose(2) << "Number of cells per axis are " << N[0] << ", " << N[1] << " and " << N[2] << "." << endl; 59 59 60 61 62 63 64 65 66 67 68 69 70 60 // 3. allocate the lists 61 cout << Verbose(2) << "Allocating cells ... "; 62 if (LC != NULL) { 63 cout << Verbose(1) << "ERROR: Linked Cell list is already allocated, I do nothing." << endl; 64 return; 65 } 66 LC = new LinkedAtoms[N[0]*N[1]*N[2]]; 67 for (index=0;index<N[0]*N[1]*N[2];index++) { 68 LC [index].clear(); 69 } 70 cout << "done." << endl; 71 71 72 72 // 4. put each atom into its respective cell 73 73 cout << Verbose(2) << "Filling cells ... "; 74 75 76 77 78 79 80 81 82 83 74 Walker = mol->start; 75 while (Walker->next != mol->end) { 76 Walker = Walker->next; 77 for (int i=0;i<NDIM;i++) { 78 n[i] = (int)floor((Walker->x.x[i] - min.x[i])/RADIUS); 79 } 80 index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2]; 81 LC[index].push_back(Walker); 82 //cout << Verbose(2) << *Walker << " goes into cell " << n[0] << ", " << n[1] << ", " << n[2] << " with No. " << index << "." << endl; 83 } 84 84 cout << "done." << endl; 85 85 cout << Verbose(1) << "End of LinkedCell" << endl; 86 86 }; 87 87 … … 90 90 LinkedCell::~LinkedCell() 91 91 { 92 93 94 95 96 97 98 99 100 92 if (LC != NULL) 93 for (index=0;index<N[0]*N[1]*N[2];index++) 94 LC[index].clear(); 95 delete[](LC); 96 for(int i=0;i<NDIM;i++) 97 N[i] = 0; 98 index = -1; 99 max.Zero(); 100 min.Zero(); 101 101 }; 102 102 … … 106 106 bool LinkedCell::CheckBounds() 107 107 { 108 109 110 111 112 113 108 bool status = true; 109 for(int i=0;i<NDIM;i++) 110 status = status && ((n[i] >=0) && (n[i] < N[i])); 111 if (!status) 112 cerr << "ERROR: indices are out of bounds!" << endl; 113 return status; 114 114 }; 115 115 … … 120 120 LinkedAtoms* LinkedCell::GetCurrentCell() 121 121 { 122 123 124 125 126 127 122 if (CheckBounds()) { 123 index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2]; 124 return (&(LC[index])); 125 } else { 126 return NULL; 127 } 128 128 }; 129 129 … … 134 134 bool LinkedCell::SetIndexToAtom(atom *Walker) 135 135 { 136 137 138 139 140 141 142 143 144 145 146 147 148 136 bool status = false; 137 for (int i=0;i<NDIM;i++) { 138 n[i] = (int)floor((Walker->x.x[i] - min.x[i])/RADIUS); 139 } 140 index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2]; 141 if (CheckBounds()) { 142 for (LinkedAtoms::iterator Runner = LC[index].begin(); Runner != LC[index].end(); Runner++) 143 status = status || ((*Runner) == Walker); 144 return status; 145 } else { 146 cerr << Verbose(1) << "ERROR: Atom "<< *Walker << " at " << Walker->x << " is out of bounds." << endl; 147 return false; 148 } 149 149 }; 150 150 … … 155 155 bool LinkedCell::SetIndexToVector(Vector *x) 156 156 { 157 158 159 160 161 162 163 164 165 157 bool status = true; 158 for (int i=0;i<NDIM;i++) { 159 n[i] = (int)floor((x->x[i] - min.x[i])/RADIUS); 160 if (max.x[i] < x->x[i]) 161 status = false; 162 if (min.x[i] > x->x[i]) 163 status = false; 164 } 165 return status; 166 166 }; 167 167 -
src/linkedcell.hpp
r205ccd r042f82 12 12 13 13 class LinkedCell{ 14 15 Vector max;// upper boundary16 Vector min;// lower boundary17 LinkedAtoms *LC;// linked cell list18 double RADIUS;// cell edge length19 int N[NDIM];// number of cells per axis20 int n[NDIM];// temporary variable for current cell per axis21 int index;// temporary index variable , access by index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2];14 public: 15 Vector max; // upper boundary 16 Vector min; // lower boundary 17 LinkedAtoms *LC; // linked cell list 18 double RADIUS; // cell edge length 19 int N[NDIM]; // number of cells per axis 20 int n[NDIM]; // temporary variable for current cell per axis 21 int index; // temporary index variable , access by index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2]; 22 22 23 24 25 26 27 28 29 23 LinkedCell(); 24 LinkedCell(molecule *mol, double RADIUS); 25 ~LinkedCell(); 26 LinkedAtoms* GetCurrentCell(); 27 bool SetIndexToAtom(atom *Walker); 28 bool SetIndexToVector(Vector *x); 29 bool CheckBounds(); 30 30 31 32 33 34 31 // not implemented yet 32 bool AddAtom(atom *Walker); 33 bool DeleteAtom(atom *Walker); 34 bool MoveAtom(atom *Walker); 35 35 }; 36 36 -
src/moleculelist.cpp
r205ccd r042f82 523 523 524 524 // open file for the force factors 525 *out << Verbose(1) << "Saving 525 *out << Verbose(1) << "Saving force factors ... "; 526 526 line << path << "/" << FRAGMENTPREFIX << FORCESFILE; 527 527 ForcesFile.open(line.str().c_str(), ios::out); … … 691 691 MoleculeLeafClass::MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf = NULL) 692 692 { 693 // 694 // 695 // 696 // 697 // 693 // if (Up != NULL) 694 // if (Up->DownLeaf == NULL) // are we the first down leaf for the upper leaf? 695 // Up->DownLeaf = this; 696 // UpLeaf = Up; 697 // DownLeaf = NULL; 698 698 Leaf = NULL; 699 699 previous = PreviousLeaf; … … 711 711 MoleculeLeafClass::~MoleculeLeafClass() 712 712 { 713 // 714 // 715 // 716 // 717 // 718 // 719 // 720 // 721 // 722 // 713 // if (DownLeaf != NULL) {// drop leaves further down 714 // MoleculeLeafClass *Walker = DownLeaf; 715 // MoleculeLeafClass *Next; 716 // do { 717 // Next = Walker->NextLeaf; 718 // delete(Walker); 719 // Walker = Next; 720 // } while (Walker != NULL); 721 // // Last Walker sets DownLeaf automatically to NULL 722 // } 723 723 // remove the leaf itself 724 724 if (Leaf != NULL) { … … 729 729 if (previous != NULL) 730 730 previous->next = next; 731 // 732 // 733 // NextLeaf->UpLeaf = UpLeaf;// either null as we are top level or the upleaf of the first node734 // 735 // UpLeaf->DownLeaf = NextLeaf;// either null as we are only leaf or NextLeaf if we are just the first736 // 737 // 731 // } else { // we are first in list (connects to UpLeaf->DownLeaf) 732 // if ((NextLeaf != NULL) && (NextLeaf->UpLeaf == NULL)) 733 // NextLeaf->UpLeaf = UpLeaf; // either null as we are top level or the upleaf of the first node 734 // if (UpLeaf != NULL) 735 // UpLeaf->DownLeaf = NextLeaf; // either null as we are only leaf or NextLeaf if we are just the first 736 // } 737 // UpLeaf = NULL; 738 738 if (next != NULL) // are we last in list 739 739 next->previous = previous; -
src/molecules.cpp
r205ccd r042f82 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 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 65 }; 66 66 … … 70 70 molecule::~molecule() 71 71 { 72 73 74 75 76 77 78 79 80 81 72 if (ListOfBondsPerAtom != NULL) 73 for(int i=AtomCount;i--;) 74 Free((void **)&ListOfBondsPerAtom[i], "molecule::~molecule: ListOfBondsPerAtom[i]"); 75 Free((void **)&ListOfBondsPerAtom, "molecule::~molecule: ListOfBondsPerAtom"); 76 Free((void **)&NumberOfBondsPerAtom, "molecule::~molecule: NumberOfBondsPerAtom"); 77 CleanupMolecule(); 78 delete(first); 79 delete(last); 80 delete(end); 81 delete(start); 82 82 }; 83 83 … … 89 89 bool molecule::AddAtom(atom *pointer) 90 90 { 91 92 93 pointer->nr = last_atom++;// increase number within molecule94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 91 if (pointer != NULL) { 92 pointer->sort = &pointer->nr; 93 pointer->nr = last_atom++; // increase number within molecule 94 AtomCount++; 95 if (pointer->type != NULL) { 96 if (ElementsInMolecule[pointer->type->Z] == 0) 97 ElementCount++; 98 ElementsInMolecule[pointer->type->Z]++; // increase number of elements 99 if (pointer->type->Z != 1) 100 NoNonHydrogen++; 101 if (pointer->Name == NULL) { 102 Free((void **)&pointer->Name, "molecule::AddAtom: *pointer->Name"); 103 pointer->Name = (char *) Malloc(sizeof(char)*6, "molecule::AddAtom: *pointer->Name"); 104 sprintf(pointer->Name, "%2s%02d", pointer->type->symbol, pointer->nr+1); 105 } 106 } 107 return add(pointer, end); 108 } else 109 return false; 110 110 }; 111 111 … … 117 117 atom * molecule::AddCopyAtom(atom *pointer) 118 118 { 119 120 121 walker->type = pointer->type;// copy element of atom122 123 124 125 126 walker->nr = last_atom++;// increase number within molecule127 128 129 130 131 132 133 134 135 136 119 if (pointer != NULL) { 120 atom *walker = new atom(); 121 walker->type = pointer->type; // copy element of atom 122 walker->x.CopyVector(&pointer->x); // copy coordination 123 walker->v.CopyVector(&pointer->v); // copy velocity 124 walker->FixedIon = pointer->FixedIon; 125 walker->sort = &walker->nr; 126 walker->nr = last_atom++; // increase number within molecule 127 walker->father = pointer; //->GetTrueFather(); 128 walker->Name = (char *) Malloc(sizeof(char)*strlen(pointer->Name)+1, "molecule::AddCopyAtom: *Name"); 129 strcpy (walker->Name, pointer->Name); 130 add(walker, end); 131 if ((pointer->type != NULL) && (pointer->type->Z != 1)) 132 NoNonHydrogen++; 133 AtomCount++; 134 return walker; 135 } else 136 return NULL; 137 137 }; 138 138 … … 142 142 * -# Single Bond: Simply add new atom with bond distance rescaled to typical hydrogen one 143 143 * -# Double Bond: Here, we need the **BondList of the \a *origin atom, by scanning for the other bonds instead of 144 * 145 * 146 * 147 * 148 * 144 * *Bond, we use the through these connected atoms to determine the plane they lie in, vector::MakeNormalvector(). 145 * The orthonormal vector to this plane along with the vector in *Bond direction determines the plane the two 146 * replacing hydrogens shall lie in. Now, all remains to do is take the usual hydrogen double bond angle for the 147 * element of *origin and form the sin/cos admixture of both plane vectors for the new coordinates of the two 148 * hydrogens forming this angle with *origin. 149 149 * -# 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 150 * 151 * 152 * 153 * 154 * 155 * 156 * 157 * 158 * 159 * 160 * 161 * 162 * 150 * triangle formed by the to be added hydrogens are not equal to the typical bond distance \f$l\f$ but have to be 151 * determined from the typical angle \f$\alpha\f$ for a hydrogen triple connected to the element of *origin): 152 * We have the height \f$d\f$ as the vector in *Bond direction (from triangle C1-H1-H2). 153 * \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 )}} 154 * \f] 155 * vector::GetNormalvector() creates one orthonormal vector from this *Bond vector and vector::MakeNormalvector creates 156 * the third one from the former two vectors. The latter ones form the plane of the base triangle mentioned above. 157 * The lengths for these are \f$f\f$ and \f$g\f$ (from triangle H1-H2-(center of H1-H2-H3)) with knowledge that 158 * the median lines in an isosceles triangle meet in the center point with a ratio 2:1. 159 * \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2} 160 * \f] 161 * as the coordination of all three atoms in the coordinate system of these three vectors: 162 * \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$. 163 163 * 164 164 * \param *out output stream for debugging … … 168 168 * \param *replacement pointer to the atom which shall be copied as a hydrogen atom in this molecule 169 169 * \param **BondList list of bonds \a *replacement has (necessary to determine plane for double and triple bonds) 170 * \param NumBond 170 * \param NumBond number of bonds in \a **BondList 171 171 * \param isAngstroem whether the coordination of the given atoms is in AtomicLength (false) or Angstrom(true) 172 172 * \return number of atoms added, if < bond::BondDegree then something went wrong … … 175 175 bool molecule::AddHydrogenReplacementAtom(ofstream *out, bond *TopBond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem) 176 176 { 177 double bondlength;// bond length of the bond to be replaced/cut178 double bondangle;// bond angle of the bond to be replaced/cut179 double BondRescale;// rescale value for the hydrogen bond length180 bool AllWentWell = true;// flag gathering the boolean return value of molecule::AddAtom and other functions, as return value on exit181 182 183 double b,l,d,f,g, alpha, factors[NDIM];// hold temporary values in triple bond case for coordination determination184 Vector Orthovector1, Orthovector2;// temporary vectors in coordination construction185 Vector InBondvector;// vector in direction of *Bond186 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 FirstOtherAtom = new atom();// new atom235 FirstOtherAtom->type = elemente->FindElement(1);// element is Hydrogen236 237 238 239 240 241 242 FirstOtherAtom->father = NULL;// if we replace hydrogen, we mark it as our father, otherwise we are just an added hydrogen with no father243 244 InBondvector.Scale(&BondRescale);// rescale the distance vector to Hydrogen bond length245 246 FirstOtherAtom->x.AddVector(&InBondvector);// ... and add distance vector to replacement atom247 248 // 249 // 250 // 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 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)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 FirstOtherAtom->father = NULL;// we are just an added hydrogen with no father300 SecondOtherAtom->father = NULL; //we are just an added hydrogen with no father301 302 303 304 305 306 307 308 // 309 // 310 // 311 // 312 // 313 // 314 // 315 316 317 318 319 320 321 FirstOtherAtom->x.Scale(&BondRescale);// rescale by correct BondDistance322 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 FirstOtherAtom->father = NULL; //we are just an added hydrogen with no father359 SecondOtherAtom->father = NULL; //we are just an added hydrogen with no father360 ThirdOtherAtom->father = NULL; //we are just an added hydrogen with no father361 362 363 364 // 365 // 366 // 367 368 // 369 // 370 // 371 372 373 alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.;// retrieve triple bond angle from database374 l = BondRescale;// desired bond length375 b = 2.*l*sin(alpha);// base length of isosceles triangle376 d = l*sqrt(cos(alpha)*cos(alpha) - sin(alpha)*sin(alpha)/3.);// length for InBondvector377 f = b/sqrt(3.);// length for Orthvector1378 g = b/2.;// length for Orthvector2379 // 380 // *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;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 417 418 419 420 421 422 423 424 425 426 427 428 429 430 // 431 177 double bondlength; // bond length of the bond to be replaced/cut 178 double bondangle; // bond angle of the bond to be replaced/cut 179 double BondRescale; // rescale value for the hydrogen bond length 180 bool AllWentWell = true; // flag gathering the boolean return value of molecule::AddAtom and other functions, as return value on exit 181 bond *FirstBond = NULL, *SecondBond = NULL; // Other bonds in double bond case to determine "other" plane 182 atom *FirstOtherAtom = NULL, *SecondOtherAtom = NULL, *ThirdOtherAtom = NULL; // pointer to hydrogen atoms to be added 183 double b,l,d,f,g, alpha, factors[NDIM]; // hold temporary values in triple bond case for coordination determination 184 Vector Orthovector1, Orthovector2; // temporary vectors in coordination construction 185 Vector InBondvector; // vector in direction of *Bond 186 bond *Binder = NULL; 187 double *matrix; 188 189 // *out << Verbose(3) << "Begin of AddHydrogenReplacementAtom." << endl; 190 // create vector in direction of bond 191 InBondvector.CopyVector(&TopReplacement->x); 192 InBondvector.SubtractVector(&TopOrigin->x); 193 bondlength = InBondvector.Norm(); 194 195 // is greater than typical bond distance? Then we have to correct periodically 196 // the problem is not the H being out of the box, but InBondvector have the wrong direction 197 // due to TopReplacement or Origin being on the wrong side! 198 if (bondlength > BondDistance) { 199 // *out << Verbose(4) << "InBondvector is: "; 200 // InBondvector.Output(out); 201 // *out << endl; 202 Orthovector1.Zero(); 203 for (int i=NDIM;i--;) { 204 l = TopReplacement->x.x[i] - TopOrigin->x.x[i]; 205 if (fabs(l) > BondDistance) { // is component greater than bond distance 206 Orthovector1.x[i] = (l < 0) ? -1. : +1.; 207 } // (signs are correct, was tested!) 208 } 209 matrix = ReturnFullMatrixforSymmetric(cell_size); 210 Orthovector1.MatrixMultiplication(matrix); 211 InBondvector.SubtractVector(&Orthovector1); // subtract just the additional translation 212 Free((void **)&matrix, "molecule::AddHydrogenReplacementAtom: *matrix"); 213 bondlength = InBondvector.Norm(); 214 // *out << Verbose(4) << "Corrected InBondvector is now: "; 215 // InBondvector.Output(out); 216 // *out << endl; 217 } // periodic correction finished 218 219 InBondvector.Normalize(); 220 // get typical bond length and store as scale factor for later 221 BondRescale = TopOrigin->type->HBondDistance[TopBond->BondDegree-1]; 222 if (BondRescale == -1) { 223 cerr << Verbose(3) << "ERROR: There is no typical hydrogen bond distance in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 224 return false; 225 BondRescale = bondlength; 226 } else { 227 if (!IsAngstroem) 228 BondRescale /= (1.*AtomicLengthToAngstroem); 229 } 230 231 // discern single, double and triple bonds 232 switch(TopBond->BondDegree) { 233 case 1: 234 FirstOtherAtom = new atom(); // new atom 235 FirstOtherAtom->type = elemente->FindElement(1); // element is Hydrogen 236 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 237 FirstOtherAtom->FixedIon = TopReplacement->FixedIon; 238 if (TopReplacement->type->Z == 1) { // neither rescale nor replace if it's already hydrogen 239 FirstOtherAtom->father = TopReplacement; 240 BondRescale = bondlength; 241 } else { 242 FirstOtherAtom->father = NULL; // if we replace hydrogen, we mark it as our father, otherwise we are just an added hydrogen with no father 243 } 244 InBondvector.Scale(&BondRescale); // rescale the distance vector to Hydrogen bond length 245 FirstOtherAtom->x.CopyVector(&TopOrigin->x); // set coordination to origin ... 246 FirstOtherAtom->x.AddVector(&InBondvector); // ... and add distance vector to replacement atom 247 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom); 248 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: "; 249 // FirstOtherAtom->x.Output(out); 250 // *out << endl; 251 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1); 252 Binder->Cyclic = false; 253 Binder->Type = TreeEdge; 254 break; 255 case 2: 256 // determine two other bonds (warning if there are more than two other) plus valence sanity check 257 for (int i=0;i<NumBond;i++) { 258 if (BondList[i] != TopBond) { 259 if (FirstBond == NULL) { 260 FirstBond = BondList[i]; 261 FirstOtherAtom = BondList[i]->GetOtherAtom(TopOrigin); 262 } else if (SecondBond == NULL) { 263 SecondBond = BondList[i]; 264 SecondOtherAtom = BondList[i]->GetOtherAtom(TopOrigin); 265 } else { 266 *out << Verbose(3) << "WARNING: Detected more than four bonds for atom " << TopOrigin->Name; 267 } 268 } 269 } 270 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) 271 SecondBond = TopBond; 272 SecondOtherAtom = TopReplacement; 273 } 274 if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all 275 // *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; 276 277 // determine the plane of these two with the *origin 278 AllWentWell = AllWentWell && Orthovector1.MakeNormalVector(&TopOrigin->x, &FirstOtherAtom->x, &SecondOtherAtom->x); 279 } else { 280 Orthovector1.GetOneNormalVector(&InBondvector); 281 } 282 //*out << Verbose(3)<< "Orthovector1: "; 283 //Orthovector1.Output(out); 284 //*out << endl; 285 // orthogonal vector and bond vector between origin and replacement form the new plane 286 Orthovector1.MakeNormalVector(&InBondvector); 287 Orthovector1.Normalize(); 288 //*out << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl; 289 290 // create the two Hydrogens ... 291 FirstOtherAtom = new atom(); 292 SecondOtherAtom = new atom(); 293 FirstOtherAtom->type = elemente->FindElement(1); 294 SecondOtherAtom->type = elemente->FindElement(1); 295 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 296 FirstOtherAtom->FixedIon = TopReplacement->FixedIon; 297 SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 298 SecondOtherAtom->FixedIon = TopReplacement->FixedIon; 299 FirstOtherAtom->father = NULL; // we are just an added hydrogen with no father 300 SecondOtherAtom->father = NULL; // we are just an added hydrogen with no father 301 bondangle = TopOrigin->type->HBondAngle[1]; 302 if (bondangle == -1) { 303 *out << Verbose(3) << "ERROR: There is no typical hydrogen bond angle in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 304 return false; 305 bondangle = 0; 306 } 307 bondangle *= M_PI/180./2.; 308 // *out << Verbose(3) << "ReScaleCheck: InBondvector "; 309 // InBondvector.Output(out); 310 // *out << endl; 311 // *out << Verbose(3) << "ReScaleCheck: Orthovector "; 312 // Orthovector1.Output(out); 313 // *out << endl; 314 // *out << Verbose(3) << "Half the bond angle is " << bondangle << ", sin and cos of it: " << sin(bondangle) << ", " << cos(bondangle) << endl; 315 FirstOtherAtom->x.Zero(); 316 SecondOtherAtom->x.Zero(); 317 for(int i=NDIM;i--;) { // rotate by half the bond angle in both directions (InBondvector is bondangle = 0 direction) 318 FirstOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (sin(bondangle)); 319 SecondOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (-sin(bondangle)); 320 } 321 FirstOtherAtom->x.Scale(&BondRescale); // rescale by correct BondDistance 322 SecondOtherAtom->x.Scale(&BondRescale); 323 //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl; 324 for(int i=NDIM;i--;) { // and make relative to origin atom 325 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i]; 326 SecondOtherAtom->x.x[i] += TopOrigin->x.x[i]; 327 } 328 // ... and add to molecule 329 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom); 330 AllWentWell = AllWentWell && AddAtom(SecondOtherAtom); 331 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: "; 332 // FirstOtherAtom->x.Output(out); 333 // *out << endl; 334 // *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: "; 335 // SecondOtherAtom->x.Output(out); 336 // *out << endl; 337 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1); 338 Binder->Cyclic = false; 339 Binder->Type = TreeEdge; 340 Binder = AddBond(BottomOrigin, SecondOtherAtom, 1); 341 Binder->Cyclic = false; 342 Binder->Type = TreeEdge; 343 break; 344 case 3: 345 // take the "usual" tetraoidal angle and add the three Hydrogen in direction of the bond (height of the tetraoid) 346 FirstOtherAtom = new atom(); 347 SecondOtherAtom = new atom(); 348 ThirdOtherAtom = new atom(); 349 FirstOtherAtom->type = elemente->FindElement(1); 350 SecondOtherAtom->type = elemente->FindElement(1); 351 ThirdOtherAtom->type = elemente->FindElement(1); 352 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 353 FirstOtherAtom->FixedIon = TopReplacement->FixedIon; 354 SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 355 SecondOtherAtom->FixedIon = TopReplacement->FixedIon; 356 ThirdOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 357 ThirdOtherAtom->FixedIon = TopReplacement->FixedIon; 358 FirstOtherAtom->father = NULL; // we are just an added hydrogen with no father 359 SecondOtherAtom->father = NULL; // we are just an added hydrogen with no father 360 ThirdOtherAtom->father = NULL; // we are just an added hydrogen with no father 361 362 // we need to vectors orthonormal the InBondvector 363 AllWentWell = AllWentWell && Orthovector1.GetOneNormalVector(&InBondvector); 364 // *out << Verbose(3) << "Orthovector1: "; 365 // Orthovector1.Output(out); 366 // *out << endl; 367 AllWentWell = AllWentWell && Orthovector2.MakeNormalVector(&InBondvector, &Orthovector1); 368 // *out << Verbose(3) << "Orthovector2: "; 369 // Orthovector2.Output(out); 370 // *out << endl; 371 372 // create correct coordination for the three atoms 373 alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.; // retrieve triple bond angle from database 374 l = BondRescale; // desired bond length 375 b = 2.*l*sin(alpha); // base length of isosceles triangle 376 d = l*sqrt(cos(alpha)*cos(alpha) - sin(alpha)*sin(alpha)/3.); // length for InBondvector 377 f = b/sqrt(3.); // length for Orthvector1 378 g = b/2.; // length for Orthvector2 379 // *out << Verbose(3) << "Bond length and half-angle: " << l << ", " << alpha << "\t (b,d,f,g) = " << b << ", " << d << ", " << f << ", " << g << ", " << endl; 380 // *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; 381 factors[0] = d; 382 factors[1] = f; 383 factors[2] = 0.; 384 FirstOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 385 factors[1] = -0.5*f; 386 factors[2] = g; 387 SecondOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 388 factors[2] = -g; 389 ThirdOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 390 391 // rescale each to correct BondDistance 392 // FirstOtherAtom->x.Scale(&BondRescale); 393 // SecondOtherAtom->x.Scale(&BondRescale); 394 // ThirdOtherAtom->x.Scale(&BondRescale); 395 396 // and relative to *origin atom 397 FirstOtherAtom->x.AddVector(&TopOrigin->x); 398 SecondOtherAtom->x.AddVector(&TopOrigin->x); 399 ThirdOtherAtom->x.AddVector(&TopOrigin->x); 400 401 // ... and add to molecule 402 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom); 403 AllWentWell = AllWentWell && AddAtom(SecondOtherAtom); 404 AllWentWell = AllWentWell && AddAtom(ThirdOtherAtom); 405 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: "; 406 // FirstOtherAtom->x.Output(out); 407 // *out << endl; 408 // *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: "; 409 // SecondOtherAtom->x.Output(out); 410 // *out << endl; 411 // *out << Verbose(4) << "Added " << *ThirdOtherAtom << " at: "; 412 // ThirdOtherAtom->x.Output(out); 413 // *out << endl; 414 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1); 415 Binder->Cyclic = false; 416 Binder->Type = TreeEdge; 417 Binder = AddBond(BottomOrigin, SecondOtherAtom, 1); 418 Binder->Cyclic = false; 419 Binder->Type = TreeEdge; 420 Binder = AddBond(BottomOrigin, ThirdOtherAtom, 1); 421 Binder->Cyclic = false; 422 Binder->Type = TreeEdge; 423 break; 424 default: 425 cerr << "ERROR: BondDegree does not state single, double or triple bond!" << endl; 426 AllWentWell = false; 427 break; 428 } 429 430 // *out << Verbose(3) << "End of AddHydrogenReplacementAtom." << endl; 431 return AllWentWell; 432 432 }; 433 433 … … 439 439 bool molecule::AddXYZFile(string filename) 440 440 { 441 442 443 444 atom *Walker = NULL;// pointer to added atom445 char shorthand[3];// shorthand for atom name446 ifstream xyzfile;// xyz file447 string line;// currently parsed line448 double x[3];// atom coordinates449 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 AddAtom(Walker);// add to molecule490 491 492 493 494 441 istringstream *input = NULL; 442 int NumberOfAtoms = 0; // atom number in xyz read 443 int i, j; // loop variables 444 atom *Walker = NULL; // pointer to added atom 445 char shorthand[3]; // shorthand for atom name 446 ifstream xyzfile; // xyz file 447 string line; // currently parsed line 448 double x[3]; // atom coordinates 449 450 xyzfile.open(filename.c_str()); 451 if (!xyzfile) 452 return false; 453 454 getline(xyzfile,line,'\n'); // Read numer of atoms in file 455 input = new istringstream(line); 456 *input >> NumberOfAtoms; 457 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl; 458 getline(xyzfile,line,'\n'); // Read comment 459 cout << Verbose(1) << "Comment: " << line << endl; 460 461 if (MDSteps == 0) // no atoms yet present 462 MDSteps++; 463 for(i=0;i<NumberOfAtoms;i++){ 464 Walker = new atom; 465 getline(xyzfile,line,'\n'); 466 istringstream *item = new istringstream(line); 467 //istringstream input(line); 468 //cout << Verbose(1) << "Reading: " << line << endl; 469 *item >> shorthand; 470 *item >> x[0]; 471 *item >> x[1]; 472 *item >> x[2]; 473 Walker->type = elemente->FindElement(shorthand); 474 if (Walker->type == NULL) { 475 cerr << "Could not parse the element at line: '" << line << "', setting to H."; 476 Walker->type = elemente->FindElement(1); 477 } 478 if (Trajectories[Walker].R.size() <= (unsigned int)MDSteps) { 479 Trajectories[Walker].R.resize(MDSteps+10); 480 Trajectories[Walker].U.resize(MDSteps+10); 481 Trajectories[Walker].F.resize(MDSteps+10); 482 } 483 for(j=NDIM;j--;) { 484 Walker->x.x[j] = x[j]; 485 Trajectories[Walker].R.at(MDSteps-1).x[j] = x[j]; 486 Trajectories[Walker].U.at(MDSteps-1).x[j] = 0; 487 Trajectories[Walker].F.at(MDSteps-1).x[j] = 0; 488 } 489 AddAtom(Walker); // add to molecule 490 delete(item); 491 } 492 xyzfile.close(); 493 delete(input); 494 return true; 495 495 }; 496 496 … … 500 500 molecule *molecule::CopyMolecule() 501 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 if (Walker->father->father == Walker->father)// same atom in copy's father points to itself543 Walker->father = Walker;// set father to itself (copy of a whole molecule)544 545 Walker->father = Walker->father->father;// set father to original's father546 547 548 549 550 if (first->next != last) {// if adjaceny list is present551 552 553 554 555 502 molecule *copy = new molecule(elemente); 503 atom *CurrentAtom = NULL; 504 atom *LeftAtom = NULL, *RightAtom = NULL; 505 atom *Walker = NULL; 506 507 // copy all atoms 508 Walker = start; 509 while(Walker->next != end) { 510 Walker = Walker->next; 511 CurrentAtom = copy->AddCopyAtom(Walker); 512 } 513 514 // copy all bonds 515 bond *Binder = first; 516 bond *NewBond = NULL; 517 while(Binder->next != last) { 518 Binder = Binder->next; 519 // get the pendant atoms of current bond in the copy molecule 520 LeftAtom = copy->start; 521 while (LeftAtom->next != copy->end) { 522 LeftAtom = LeftAtom->next; 523 if (LeftAtom->father == Binder->leftatom) 524 break; 525 } 526 RightAtom = copy->start; 527 while (RightAtom->next != copy->end) { 528 RightAtom = RightAtom->next; 529 if (RightAtom->father == Binder->rightatom) 530 break; 531 } 532 NewBond = copy->AddBond(LeftAtom, RightAtom, Binder->BondDegree); 533 NewBond->Cyclic = Binder->Cyclic; 534 if (Binder->Cyclic) 535 copy->NoCyclicBonds++; 536 NewBond->Type = Binder->Type; 537 } 538 // correct fathers 539 Walker = copy->start; 540 while(Walker->next != copy->end) { 541 Walker = Walker->next; 542 if (Walker->father->father == Walker->father) // same atom in copy's father points to itself 543 Walker->father = Walker; // set father to itself (copy of a whole molecule) 544 else 545 Walker->father = Walker->father->father; // set father to original's father 546 } 547 // copy values 548 copy->CountAtoms((ofstream *)&cout); 549 copy->CountElements(); 550 if (first->next != last) { // if adjaceny list is present 551 copy->BondDistance = BondDistance; 552 copy->CreateListOfBondsPerAtom((ofstream *)&cout); 553 } 554 555 return copy; 556 556 }; 557 557 … … 564 564 bond * molecule::AddBond(atom *atom1, atom *atom2, int degree=1) 565 565 { 566 567 568 569 570 571 572 573 574 575 566 bond *Binder = NULL; 567 if ((atom1 != NULL) && (FindAtom(atom1->nr) != NULL) && (atom2 != NULL) && (FindAtom(atom2->nr) != NULL)) { 568 Binder = new bond(atom1, atom2, degree, BondCount++); 569 if ((atom1->type != NULL) && (atom1->type->Z != 1) && (atom2->type != NULL) && (atom2->type->Z != 1)) 570 NoNonBonds++; 571 add(Binder, last); 572 } else { 573 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; 574 } 575 return Binder; 576 576 }; 577 577 … … 583 583 bool molecule::RemoveBond(bond *pointer) 584 584 { 585 586 587 585 //cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl; 586 removewithoutcheck(pointer); 587 return true; 588 588 }; 589 589 … … 595 595 bool molecule::RemoveBonds(atom *BondPartner) 596 596 { 597 598 597 cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl; 598 return false; 599 599 }; 600 600 … … 619 619 void molecule::SetBoxDimension(Vector *dim) 620 620 { 621 622 623 624 625 626 621 cell_size[0] = dim->x[0]; 622 cell_size[1] = 0.; 623 cell_size[2] = dim->x[1]; 624 cell_size[3] = 0.; 625 cell_size[4] = 0.; 626 cell_size[5] = dim->x[2]; 627 627 }; 628 628 … … 632 632 bool molecule::CenterInBox(ofstream *out) 633 633 { 634 635 636 637 634 bool status = true; 635 atom *ptr = NULL; 636 Vector x; 637 double *M = ReturnFullMatrixforSymmetric(cell_size); 638 638 double *Minv = x.InverseMatrix(M); 639 640 641 // 639 double value; 640 641 // cout << "The box matrix is :" << endl; 642 642 // for (int i=0;i<NDIM;++i) { 643 643 // for (int j=0;j<NDIM;++j) … … 651 651 // cout << endl; 652 652 // } 653 653 // go through all atoms 654 654 ptr = start->next; // start at first in list 655 655 if (ptr != end) { //list not empty? … … 676 676 delete(M); 677 677 delete(Minv); 678 678 return status; 679 679 }; 680 680 … … 685 685 void molecule::CenterEdge(ofstream *out, Vector *max) 686 686 { 687 688 689 // 690 atom *ptr = start->next;// start at first in list691 if (ptr != end) {//list not empty?692 693 694 695 696 while (ptr->next != end) {// continue with second if present697 698 699 700 701 702 703 704 // 705 // 706 // 707 // 708 // 709 710 711 712 713 714 // 687 Vector *min = new Vector; 688 689 // *out << Verbose(3) << "Begin of CenterEdge." << endl; 690 atom *ptr = start->next; // start at first in list 691 if (ptr != end) { //list not empty? 692 for (int i=NDIM;i--;) { 693 max->x[i] = ptr->x.x[i]; 694 min->x[i] = ptr->x.x[i]; 695 } 696 while (ptr->next != end) { // continue with second if present 697 ptr = ptr->next; 698 //ptr->Output(1,1,out); 699 for (int i=NDIM;i--;) { 700 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i]; 701 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i]; 702 } 703 } 704 // *out << Verbose(4) << "Maximum is "; 705 // max->Output(out); 706 // *out << ", Minimum is "; 707 // min->Output(out); 708 // *out << endl; 709 min->Scale(-1.); 710 max->AddVector(min); 711 Translate(min); 712 } 713 delete(min); 714 // *out << Verbose(3) << "End of CenterEdge." << endl; 715 715 }; 716 716 … … 721 721 void molecule::CenterOrigin(ofstream *out, Vector *center) 722 722 { 723 724 atom *ptr = start->next;// start at first in list725 726 727 728 729 if (ptr != end) {//list not empty?730 while (ptr->next != end) {// continue with second if present731 732 733 734 735 736 737 723 int Num = 0; 724 atom *ptr = start->next; // start at first in list 725 726 for(int i=NDIM;i--;) // zero center vector 727 center->x[i] = 0.; 728 729 if (ptr != end) { //list not empty? 730 while (ptr->next != end) { // continue with second if present 731 ptr = ptr->next; 732 Num++; 733 center->AddVector(&ptr->x); 734 } 735 center->Scale(-1./Num); // divide through total number (and sign for direction) 736 Translate(center); 737 } 738 738 }; 739 739 … … 744 744 Vector * molecule::DetermineCenterOfAll(ofstream *out) 745 745 { 746 atom *ptr = start->next;// start at first in list747 748 749 750 751 752 753 if (ptr != end) {//list not empty?754 while (ptr->next != end) {// continue with second if present755 756 757 758 759 760 761 762 763 764 765 746 atom *ptr = start->next; // start at first in list 747 Vector *a = new Vector(); 748 Vector tmp; 749 double Num = 0; 750 751 a->Zero(); 752 753 if (ptr != end) { //list not empty? 754 while (ptr->next != end) { // continue with second if present 755 ptr = ptr->next; 756 Num += 1.; 757 tmp.CopyVector(&ptr->x); 758 a->AddVector(&tmp); 759 } 760 a->Scale(-1./Num); // divide through total mass (and sign for direction) 761 } 762 //cout << Verbose(1) << "Resulting center of gravity: "; 763 //a->Output(out); 764 //cout << endl; 765 return a; 766 766 }; 767 767 … … 772 772 Vector * molecule::DetermineCenterOfGravity(ofstream *out) 773 773 { 774 atom *ptr = start->next;// start at first in list775 776 777 778 779 780 781 if (ptr != end) {//list not empty?782 while (ptr->next != end) {// continue with second if present783 784 785 786 tmp.Scale(ptr->type->mass);// scale by mass787 788 789 790 791 // 792 // 793 // 794 774 atom *ptr = start->next; // start at first in list 775 Vector *a = new Vector(); 776 Vector tmp; 777 double Num = 0; 778 779 a->Zero(); 780 781 if (ptr != end) { //list not empty? 782 while (ptr->next != end) { // continue with second if present 783 ptr = ptr->next; 784 Num += ptr->type->mass; 785 tmp.CopyVector(&ptr->x); 786 tmp.Scale(ptr->type->mass); // scale by mass 787 a->AddVector(&tmp); 788 } 789 a->Scale(-1./Num); // divide through total mass (and sign for direction) 790 } 791 // *out << Verbose(1) << "Resulting center of gravity: "; 792 // a->Output(out); 793 // *out << endl; 794 return a; 795 795 }; 796 796 … … 801 801 void molecule::CenterGravity(ofstream *out, Vector *center) 802 802 { 803 804 805 806 807 808 809 803 if (center == NULL) { 804 DetermineCenter(*center); 805 Translate(center); 806 delete(center); 807 } else { 808 Translate(center); 809 } 810 810 }; 811 811 … … 815 815 void molecule::Scale(double **factor) 816 816 { 817 818 819 820 821 822 823 824 817 atom *ptr = start; 818 819 while (ptr->next != end) { 820 ptr = ptr->next; 821 for (int j=0;j<MDSteps;j++) 822 Trajectories[ptr].R.at(j).Scale(factor); 823 ptr->x.Scale(factor); 824 } 825 825 }; 826 826 … … 830 830 void molecule::Translate(const Vector *trans) 831 831 { 832 833 834 835 836 837 838 839 832 atom *ptr = start; 833 834 while (ptr->next != end) { 835 ptr = ptr->next; 836 for (int j=0;j<MDSteps;j++) 837 Trajectories[ptr].R.at(j).Translate(trans); 838 ptr->x.Translate(trans); 839 } 840 840 }; 841 841 … … 900 900 void molecule::Mirror(const Vector *n) 901 901 { 902 903 904 905 906 907 908 909 902 atom *ptr = start; 903 904 while (ptr->next != end) { 905 ptr = ptr->next; 906 for (int j=0;j<MDSteps;j++) 907 Trajectories[ptr].R.at(j).Mirror(n); 908 ptr->x.Mirror(n); 909 } 910 910 }; 911 911 … … 915 915 void molecule::DetermineCenter(Vector &Center) 916 916 { 917 918 919 920 921 922 923 924 925 926 927 928 917 atom *Walker = start; 918 bond *Binder = NULL; 919 double *matrix = ReturnFullMatrixforSymmetric(cell_size); 920 double tmp; 921 bool flag; 922 Vector Testvector, Translationvector; 923 924 do { 925 Center.Zero(); 926 flag = true; 927 while (Walker->next != end) { 928 Walker = Walker->next; 929 929 #ifdef ADDHYDROGEN 930 930 if (Walker->type->Z != 1) { 931 931 #endif 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 932 Testvector.CopyVector(&Walker->x); 933 Testvector.InverseMatrixMultiplication(matrix); 934 Translationvector.Zero(); 935 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) { 936 Binder = ListOfBondsPerAtom[Walker->nr][i]; 937 if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing 938 for (int j=0;j<NDIM;j++) { 939 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j]; 940 if ((fabs(tmp)) > BondDistance) { 941 flag = false; 942 cout << Verbose(0) << "Hit: atom " << Walker->Name << " in bond " << *Binder << " has to be shifted due to " << tmp << "." << endl; 943 if (tmp > 0) 944 Translationvector.x[j] -= 1.; 945 else 946 Translationvector.x[j] += 1.; 947 } 948 } 949 } 950 Testvector.AddVector(&Translationvector); 951 Testvector.MatrixMultiplication(matrix); 952 Center.AddVector(&Testvector); 953 cout << Verbose(1) << "vector is: "; 954 Testvector.Output((ofstream *)&cout); 955 cout << endl; 956 956 #ifdef ADDHYDROGEN 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 957 // now also change all hydrogens 958 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) { 959 Binder = ListOfBondsPerAtom[Walker->nr][i]; 960 if (Binder->GetOtherAtom(Walker)->type->Z == 1) { 961 Testvector.CopyVector(&Binder->GetOtherAtom(Walker)->x); 962 Testvector.InverseMatrixMultiplication(matrix); 963 Testvector.AddVector(&Translationvector); 964 Testvector.MatrixMultiplication(matrix); 965 Center.AddVector(&Testvector); 966 cout << Verbose(1) << "Hydrogen vector is: "; 967 Testvector.Output((ofstream *)&cout); 968 cout << endl; 969 } 970 } 971 } 972 972 #endif 973 974 975 976 973 } 974 } while (!flag); 975 Free((void **)&matrix, "molecule::DetermineCenter: *matrix"); 976 Center.Scale(1./(double)AtomCount); 977 977 }; 978 978 … … 983 983 void molecule::PrincipalAxisSystem(ofstream *out, bool DoRotate) 984 984 { 985 atom *ptr = start;// start at first in list986 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 1051 1052 1053 1054 1055 1056 1057 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 985 atom *ptr = start; // start at first in list 986 double InertiaTensor[NDIM*NDIM]; 987 Vector *CenterOfGravity = DetermineCenterOfGravity(out); 988 989 CenterGravity(out, CenterOfGravity); 990 991 // reset inertia tensor 992 for(int i=0;i<NDIM*NDIM;i++) 993 InertiaTensor[i] = 0.; 994 995 // sum up inertia tensor 996 while (ptr->next != end) { 997 ptr = ptr->next; 998 Vector x; 999 x.CopyVector(&ptr->x); 1000 //x.SubtractVector(CenterOfGravity); 1001 InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]); 1002 InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]); 1003 InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]); 1004 InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]); 1005 InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]); 1006 InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]); 1007 InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]); 1008 InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]); 1009 InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]); 1010 } 1011 // print InertiaTensor for debugging 1012 *out << "The inertia tensor is:" << endl; 1013 for(int i=0;i<NDIM;i++) { 1014 for(int j=0;j<NDIM;j++) 1015 *out << InertiaTensor[i*NDIM+j] << " "; 1016 *out << endl; 1017 } 1018 *out << endl; 1019 1020 // diagonalize to determine principal axis system 1021 gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(NDIM); 1022 gsl_matrix_view m = gsl_matrix_view_array(InertiaTensor, NDIM, NDIM); 1023 gsl_vector *eval = gsl_vector_alloc(NDIM); 1024 gsl_matrix *evec = gsl_matrix_alloc(NDIM, NDIM); 1025 gsl_eigen_symmv(&m.matrix, eval, evec, T); 1026 gsl_eigen_symmv_free(T); 1027 gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC); 1028 1029 for(int i=0;i<NDIM;i++) { 1030 *out << Verbose(1) << "eigenvalue = " << gsl_vector_get(eval, i); 1031 *out << ", eigenvector = (" << evec->data[i * evec->tda + 0] << "," << evec->data[i * evec->tda + 1] << "," << evec->data[i * evec->tda + 2] << ")" << endl; 1032 } 1033 1034 // check whether we rotate or not 1035 if (DoRotate) { 1036 *out << Verbose(1) << "Transforming molecule into PAS ... "; 1037 // the eigenvectors specify the transformation matrix 1038 ptr = start; 1039 while (ptr->next != end) { 1040 ptr = ptr->next; 1041 for (int j=0;j<MDSteps;j++) 1042 Trajectories[ptr].R.at(j).MatrixMultiplication(evec->data); 1043 ptr->x.MatrixMultiplication(evec->data); 1044 } 1045 *out << "done." << endl; 1046 1047 // summing anew for debugging (resulting matrix has to be diagonal!) 1048 // reset inertia tensor 1049 for(int i=0;i<NDIM*NDIM;i++) 1050 InertiaTensor[i] = 0.; 1051 1052 // sum up inertia tensor 1053 ptr = start; 1054 while (ptr->next != end) { 1055 ptr = ptr->next; 1056 Vector x; 1057 x.CopyVector(&ptr->x); 1058 //x.SubtractVector(CenterOfGravity); 1059 InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]); 1060 InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]); 1061 InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]); 1062 InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]); 1063 InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]); 1064 InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]); 1065 InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]); 1066 InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]); 1067 InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]); 1068 } 1069 // print InertiaTensor for debugging 1070 *out << "The inertia tensor is:" << endl; 1071 for(int i=0;i<NDIM;i++) { 1072 for(int j=0;j<NDIM;j++) 1073 *out << InertiaTensor[i*NDIM+j] << " "; 1074 *out << endl; 1075 } 1076 *out << endl; 1077 } 1078 1079 // free everything 1080 delete(CenterOfGravity); 1081 gsl_vector_free(eval); 1082 gsl_matrix_free(evec); 1083 1083 }; 1084 1084 … … 1094 1094 bool molecule::VerletForceIntegration(char *file, double delta_t, bool IsAngstroem) 1095 1095 { 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 CountElements();// make sure ElementsInMolecule is up to date1107 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 a = delta_t*0.5/IonMass;// (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 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 * t1157 1158 1159 1160 1161 1162 1163 // 1164 // 1165 // cout << Trajectories[walker].R.at(MDSteps).x[d] << " ";// next step1166 // 1167 // 1168 // cout << Trajectories[walker].U.at(MDSteps).x[d] << " ";// next step1169 // 1170 1171 1172 1173 1174 1175 1176 1177 // 1178 // 1179 // 1180 // 1181 // 1182 // 1183 // IonMass += walker->type->mass;// sum up total mass1184 // 1185 // 1186 // 1187 // 1188 // 1189 // 1190 // 1191 // 1192 // 1193 // 1194 // 1195 1196 1197 1198 1199 1096 element *runner = elemente->start; 1097 atom *walker = NULL; 1098 int AtomNo; 1099 ifstream input(file); 1100 string token; 1101 stringstream item; 1102 double a, IonMass; 1103 ForceMatrix Force; 1104 Vector tmpvector; 1105 1106 CountElements(); // make sure ElementsInMolecule is up to date 1107 1108 // check file 1109 if (input == NULL) { 1110 return false; 1111 } else { 1112 // parse file into ForceMatrix 1113 if (!Force.ParseMatrix(file, 0,0,0)) { 1114 cerr << "Could not parse Force Matrix file " << file << "." << endl; 1115 return false; 1116 } 1117 if (Force.RowCounter[0] != AtomCount) { 1118 cerr << "Mismatch between number of atoms in file " << Force.RowCounter[0] << " and in molecule " << AtomCount << "." << endl; 1119 return false; 1120 } 1121 // correct Forces 1122 // for(int d=0;d<NDIM;d++) 1123 // tmpvector.x[d] = 0.; 1124 // for(int i=0;i<AtomCount;i++) 1125 // for(int d=0;d<NDIM;d++) { 1126 // tmpvector.x[d] += Force.Matrix[0][i][d+5]; 1127 // } 1128 // for(int i=0;i<AtomCount;i++) 1129 // for(int d=0;d<NDIM;d++) { 1130 // Force.Matrix[0][i][d+5] -= tmpvector.x[d]/(double)AtomCount; 1131 // } 1132 // and perform Verlet integration for each atom with position, velocity and force vector 1133 runner = elemente->start; 1134 while (runner->next != elemente->end) { // go through every element 1135 runner = runner->next; 1136 IonMass = runner->mass; 1137 a = delta_t*0.5/IonMass; // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a 1138 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1139 AtomNo = 0; 1140 walker = start; 1141 while (walker->next != end) { // go through every atom of this element 1142 walker = walker->next; 1143 if (walker->type == runner) { // if this atom fits to element 1144 // check size of vectors 1145 if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) { 1146 //cout << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl; 1147 Trajectories[walker].R.resize(MDSteps+10); 1148 Trajectories[walker].U.resize(MDSteps+10); 1149 Trajectories[walker].F.resize(MDSteps+10); 1150 } 1151 // 1. calculate x(t+\delta t) 1152 for (int d=0; d<NDIM; d++) { 1153 Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5]; 1154 Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d]; 1155 Trajectories[walker].R.at(MDSteps).x[d] += delta_t*(Trajectories[walker].U.at(MDSteps-1).x[d]); 1156 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 1157 } 1158 // 2. Calculate v(t+\delta t) 1159 for (int d=0; d<NDIM; d++) { 1160 Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d]; 1161 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; 1162 } 1163 // cout << "Integrated position&velocity of step " << (MDSteps) << ": ("; 1164 // for (int d=0;d<NDIM;d++) 1165 // cout << Trajectories[walker].R.at(MDSteps).x[d] << " "; // next step 1166 // cout << ")\t("; 1167 // for (int d=0;d<NDIM;d++) 1168 // cout << Trajectories[walker].U.at(MDSteps).x[d] << " "; // next step 1169 // cout << ")" << endl; 1170 // next atom 1171 AtomNo++; 1172 } 1173 } 1174 } 1175 } 1176 } 1177 // // correct velocities (rather momenta) so that center of mass remains motionless 1178 // tmpvector.zero() 1179 // IonMass = 0.; 1180 // walker = start; 1181 // while (walker->next != end) { // go through every atom 1182 // walker = walker->next; 1183 // IonMass += walker->type->mass; // sum up total mass 1184 // for(int d=0;d<NDIM;d++) { 1185 // tmpvector.x[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass; 1186 // } 1187 // } 1188 // walker = start; 1189 // while (walker->next != end) { // go through every atom of this element 1190 // walker = walker->next; 1191 // for(int d=0;d<NDIM;d++) { 1192 // Trajectories[walker].U.at(MDSteps).x[d] -= tmpvector.x[d]*walker->type->mass/IonMass; 1193 // } 1194 // } 1195 MDSteps++; 1196 1197 1198 // exit 1199 return true; 1200 1200 }; 1201 1201 … … 1205 1205 void molecule::Align(Vector *n) 1206 1206 { 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 ptr->x.x[0] =cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];1222 1223 1224 1225 Trajectories[ptr].R.at(j).x[0] =cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];1226 1227 1228 1229 1230 1231 n->x[0] = cos(alpha) * tmp +sin(alpha) * n->x[2];1232 n->x[2] = -sin(alpha) * tmp +cos(alpha) * n->x[2];1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 ptr->x.x[1] =cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];1245 1246 1247 1248 Trajectories[ptr].R.at(j).x[1] =cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];1249 1250 1251 1252 1253 1254 n->x[1] = cos(alpha) * tmp +sin(alpha) * n->x[2];1255 n->x[2] = -sin(alpha) * tmp +cos(alpha) * n->x[2];1256 1257 1258 1259 1260 1207 atom *ptr = start; 1208 double alpha, tmp; 1209 Vector z_axis; 1210 z_axis.x[0] = 0.; 1211 z_axis.x[1] = 0.; 1212 z_axis.x[2] = 1.; 1213 1214 // rotate on z-x plane 1215 cout << Verbose(0) << "Begin of Aligning all atoms." << endl; 1216 alpha = atan(-n->x[0]/n->x[2]); 1217 cout << Verbose(1) << "Z-X-angle: " << alpha << " ... "; 1218 while (ptr->next != end) { 1219 ptr = ptr->next; 1220 tmp = ptr->x.x[0]; 1221 ptr->x.x[0] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1222 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1223 for (int j=0;j<MDSteps;j++) { 1224 tmp = Trajectories[ptr].R.at(j).x[0]; 1225 Trajectories[ptr].R.at(j).x[0] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1226 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1227 } 1228 } 1229 // rotate n vector 1230 tmp = n->x[0]; 1231 n->x[0] = cos(alpha) * tmp + sin(alpha) * n->x[2]; 1232 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2]; 1233 cout << Verbose(1) << "alignment vector after first rotation: "; 1234 n->Output((ofstream *)&cout); 1235 cout << endl; 1236 1237 // rotate on z-y plane 1238 ptr = start; 1239 alpha = atan(-n->x[1]/n->x[2]); 1240 cout << Verbose(1) << "Z-Y-angle: " << alpha << " ... "; 1241 while (ptr->next != end) { 1242 ptr = ptr->next; 1243 tmp = ptr->x.x[1]; 1244 ptr->x.x[1] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1245 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1246 for (int j=0;j<MDSteps;j++) { 1247 tmp = Trajectories[ptr].R.at(j).x[1]; 1248 Trajectories[ptr].R.at(j).x[1] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1249 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1250 } 1251 } 1252 // rotate n vector (for consistency check) 1253 tmp = n->x[1]; 1254 n->x[1] = cos(alpha) * tmp + sin(alpha) * n->x[2]; 1255 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2]; 1256 1257 cout << Verbose(1) << "alignment vector after second rotation: "; 1258 n->Output((ofstream *)&cout); 1259 cout << Verbose(1) << endl; 1260 cout << Verbose(0) << "End of Aligning all atoms." << endl; 1261 1261 }; 1262 1262 … … 1267 1267 bool molecule::RemoveAtom(atom *pointer) 1268 1268 { 1269 if (ElementsInMolecule[pointer->type->Z] != 0)// this would indicate an error1270 ElementsInMolecule[pointer->type->Z]--;// decrease number of atom of this element1271 1272 1273 if (ElementsInMolecule[pointer->type->Z] == 0)// was last atom of this element?1274 1275 1276 1269 if (ElementsInMolecule[pointer->type->Z] != 0) // this would indicate an error 1270 ElementsInMolecule[pointer->type->Z]--; // decrease number of atom of this element 1271 else 1272 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl; 1273 if (ElementsInMolecule[pointer->type->Z] == 0) // was last atom of this element? 1274 ElementCount--; 1275 Trajectories.erase(pointer); 1276 return remove(pointer, start, end); 1277 1277 }; 1278 1278 … … 1301 1301 bool molecule::CleanupMolecule() 1302 1302 { 1303 1303 return (cleanup(start,end) && cleanup(first,last)); 1304 1304 }; 1305 1305 … … 1308 1308 * \return pointer to atom or NULL 1309 1309 */ 1310 atom * molecule::FindAtom(int Nr) 1311 1312 1313 1314 1315 1316 1317 1318 1310 atom * molecule::FindAtom(int Nr) const{ 1311 atom * walker = find(&Nr, start,end); 1312 if (walker != NULL) { 1313 //cout << Verbose(0) << "Found Atom Nr. " << walker->nr << endl; 1314 return walker; 1315 } else { 1316 cout << Verbose(0) << "Atom not found in list." << endl; 1317 return NULL; 1318 } 1319 1319 }; 1320 1320 … … 1324 1324 atom * molecule::AskAtom(string text) 1325 1325 { 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1326 int No; 1327 atom *ion = NULL; 1328 do { 1329 //cout << Verbose(0) << "============Atom list==========================" << endl; 1330 //mol->Output((ofstream *)&cout); 1331 //cout << Verbose(0) << "===============================================" << endl; 1332 cout << Verbose(0) << text; 1333 cin >> No; 1334 ion = this->FindAtom(No); 1335 } while (ion == NULL); 1336 return ion; 1337 1337 }; 1338 1338 … … 1343 1343 bool molecule::CheckBounds(const Vector *x) const 1344 1344 { 1345 1346 1347 1348 1349 1350 1351 1352 1345 bool result = true; 1346 int j =-1; 1347 for (int i=0;i<NDIM;i++) { 1348 j += i+1; 1349 result = result && ((x->x[i] >= 0) && (x->x[i] < cell_size[j])); 1350 } 1351 //return result; 1352 return true; /// probably not gonna use the check no more 1353 1353 }; 1354 1354 … … 1360 1360 double LeastSquareDistance (const gsl_vector * x, void * params) 1361 1361 { 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 c.CopyVector(&ptr->x);// copy vector to temporary one1379 c.SubtractVector(&a);// subtract offset vector1380 t = c.ScalarProduct(&b);// get direction parameter1381 d.CopyVector(&b);// and create vector1382 1383 c.SubtractVector(&d);// ... yielding distance vector1384 res += d.ScalarProduct((const Vector *)&d);// add squared distance1385 1386 1387 1362 double res = 0, t; 1363 Vector a,b,c,d; 1364 struct lsq_params *par = (struct lsq_params *)params; 1365 atom *ptr = par->mol->start; 1366 1367 // initialize vectors 1368 a.x[0] = gsl_vector_get(x,0); 1369 a.x[1] = gsl_vector_get(x,1); 1370 a.x[2] = gsl_vector_get(x,2); 1371 b.x[0] = gsl_vector_get(x,3); 1372 b.x[1] = gsl_vector_get(x,4); 1373 b.x[2] = gsl_vector_get(x,5); 1374 // go through all atoms 1375 while (ptr != par->mol->end) { 1376 ptr = ptr->next; 1377 if (ptr->type == ((struct lsq_params *)params)->type) { // for specific type 1378 c.CopyVector(&ptr->x); // copy vector to temporary one 1379 c.SubtractVector(&a); // subtract offset vector 1380 t = c.ScalarProduct(&b); // get direction parameter 1381 d.CopyVector(&b); // and create vector 1382 d.Scale(&t); 1383 c.SubtractVector(&d); // ... yielding distance vector 1384 res += d.ScalarProduct((const Vector *)&d); // add squared distance 1385 } 1386 } 1387 return res; 1388 1388 }; 1389 1389 … … 1393 1393 void molecule::GetAlignvector(struct lsq_params * par) const 1394 1394 { 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 gsl_vector_set (par->x, 0, 0.0);// offset1418 1419 1420 gsl_vector_set (par->x, 3, 0.0);// direction1421 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 1395 int np = 6; 1396 1397 const gsl_multimin_fminimizer_type *T = 1398 gsl_multimin_fminimizer_nmsimplex; 1399 gsl_multimin_fminimizer *s = NULL; 1400 gsl_vector *ss; 1401 gsl_multimin_function minex_func; 1402 1403 size_t iter = 0, i; 1404 int status; 1405 double size; 1406 1407 /* Initial vertex size vector */ 1408 ss = gsl_vector_alloc (np); 1409 1410 /* Set all step sizes to 1 */ 1411 gsl_vector_set_all (ss, 1.0); 1412 1413 /* Starting point */ 1414 par->x = gsl_vector_alloc (np); 1415 par->mol = this; 1416 1417 gsl_vector_set (par->x, 0, 0.0); // offset 1418 gsl_vector_set (par->x, 1, 0.0); 1419 gsl_vector_set (par->x, 2, 0.0); 1420 gsl_vector_set (par->x, 3, 0.0); // direction 1421 gsl_vector_set (par->x, 4, 0.0); 1422 gsl_vector_set (par->x, 5, 1.0); 1423 1424 /* Initialize method and iterate */ 1425 minex_func.f = &LeastSquareDistance; 1426 minex_func.n = np; 1427 minex_func.params = (void *)par; 1428 1429 s = gsl_multimin_fminimizer_alloc (T, np); 1430 gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss); 1431 1432 do 1433 { 1434 iter++; 1435 status = gsl_multimin_fminimizer_iterate(s); 1436 1437 if (status) 1438 break; 1439 1440 size = gsl_multimin_fminimizer_size (s); 1441 status = gsl_multimin_test_size (size, 1e-2); 1442 1443 if (status == GSL_SUCCESS) 1444 { 1445 printf ("converged to minimum at\n"); 1446 } 1447 1448 printf ("%5d ", (int)iter); 1449 for (i = 0; i < (size_t)np; i++) 1450 { 1451 printf ("%10.3e ", gsl_vector_get (s->x, i)); 1452 } 1453 printf ("f() = %7.3f size = %.3f\n", s->fval, size); 1454 } 1455 while (status == GSL_CONTINUE && iter < 100); 1456 1457 for (i=0;i<(size_t)np;i++) 1458 gsl_vector_set(par->x, i, gsl_vector_get(s->x, i)); 1459 //gsl_vector_free(par->x); 1460 gsl_vector_free(ss); 1461 gsl_multimin_fminimizer_free (s); 1462 1462 }; 1463 1463 … … 1467 1467 bool molecule::Output(ofstream *out) 1468 1468 { 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2]MoveType (0 MoveIon, 1 FixedIon)" << endl;1469 atom *walker = NULL; 1470 int ElementNo[MAX_ELEMENTS], AtomNo[MAX_ELEMENTS]; 1471 CountElements(); 1472 1473 for (int i=0;i<MAX_ELEMENTS;++i) { 1474 AtomNo[i] = 0; 1475 ElementNo[i] = 0; 1476 } 1477 if (out == NULL) { 1478 return false; 1479 } else { 1480 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2] MoveType (0 MoveIon, 1 FixedIon)" << endl; 1481 1481 walker = start; 1482 1482 while (walker->next != end) { // go through every atom of this element … … 1495 1495 walker->Output(ElementNo[walker->type->Z], AtomNo[walker->type->Z], out); // removed due to trajectories 1496 1496 } 1497 1498 1497 return true; 1498 } 1499 1499 }; 1500 1500 … … 1504 1504 bool molecule::OutputTrajectories(ofstream *out) 1505 1505 { 1506 1506 atom *walker = NULL; 1507 1507 int ElementNo[MAX_ELEMENTS], AtomNo[MAX_ELEMENTS]; 1508 1509 1510 1511 1512 1513 1514 1515 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2]MoveType (0 MoveIon, 1 FixedIon)" << endl;1516 1517 1518 1519 1520 1521 1522 1508 CountElements(); 1509 1510 if (out == NULL) { 1511 return false; 1512 } else { 1513 for (int step = 0; step < MDSteps; step++) { 1514 if (step == 0) { 1515 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2] MoveType (0 MoveIon, 1 FixedIon)" << endl; 1516 } else { 1517 *out << "# ====== MD step " << step << " =========" << endl; 1518 } 1519 for (int i=0;i<MAX_ELEMENTS;++i) { 1520 AtomNo[i] = 0; 1521 ElementNo[i] = 0; 1522 } 1523 1523 walker = start; 1524 1524 while (walker->next != end) { // go through every atom of this element … … 1535 1535 walker = walker->next; 1536 1536 AtomNo[walker->type->Z]++; 1537 *out << "Ion_Type" << ElementNo[walker->type->Z] << "_" << AtomNo[walker->type->Z] << "\t" 1537 *out << "Ion_Type" << ElementNo[walker->type->Z] << "_" << AtomNo[walker->type->Z] << "\t" << fixed << setprecision(9) << showpoint; 1538 1538 *out << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2]; 1539 1539 *out << "\t" << walker->FixedIon; … … 1544 1544 *out << "\t# Number in molecule " << walker->nr << endl; 1545 1545 } 1546 1547 1548 1546 } 1547 return true; 1548 } 1549 1549 }; 1550 1550 … … 1554 1554 void molecule::OutputListOfBonds(ofstream *out) const 1555 1555 { 1556 1557 1558 1559 1556 *out << Verbose(2) << endl << "From Contents of ListOfBondsPerAtom, all non-hydrogen atoms:" << endl; 1557 atom *Walker = start; 1558 while (Walker->next != end) { 1559 Walker = Walker->next; 1560 1560 #ifdef ADDHYDROGEN 1561 if (Walker->type->Z != 1) {// regard only non-hydrogen1561 if (Walker->type->Z != 1) { // regard only non-hydrogen 1562 1562 #endif 1563 1564 1565 1566 1563 *out << Verbose(2) << "Atom " << Walker->Name << " has Bonds: "<<endl; 1564 for(int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) { 1565 *out << Verbose(3) << *(ListOfBondsPerAtom)[Walker->nr][j] << endl; 1566 } 1567 1567 #ifdef ADDHYDROGEN 1568 1568 } 1569 1569 #endif 1570 1571 1570 } 1571 *out << endl; 1572 1572 }; 1573 1573 … … 1575 1575 * \param *out stream pointer 1576 1576 */ 1577 bool molecule::Checkout(ofstream *out) 1578 { 1579 1577 bool molecule::Checkout(ofstream *out) const 1578 { 1579 return elemente->Checkout(out, ElementsInMolecule); 1580 1580 }; 1581 1581 … … 1585 1585 bool molecule::OutputTrajectoriesXYZ(ofstream *out) 1586 1586 { 1587 1588 1589 1590 1591 now = time((time_t *)NULL);// Get the system time and put it into 'now' as 'calender time'1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1587 atom *walker = NULL; 1588 int No = 0; 1589 time_t now; 1590 1591 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 1592 walker = start; 1593 while (walker->next != end) { // go through every atom and count 1594 walker = walker->next; 1595 No++; 1596 } 1597 if (out != NULL) { 1598 for (int step=0;step<MDSteps;step++) { 1599 *out << No << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now); 1600 walker = start; 1601 while (walker->next != end) { // go through every atom of this element 1602 walker = walker->next; 1603 *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; 1604 } 1605 } 1606 return true; 1607 } else 1608 return false; 1609 1609 }; 1610 1610 … … 1614 1614 bool molecule::OutputXYZ(ofstream *out) const 1615 1615 { 1616 1617 1618 1619 1620 now = time((time_t *)NULL);// Get the system time and put it into 'now' as 'calender time'1621 1622 1623 1624 1625 1626 1627 1616 atom *walker = NULL; 1617 int AtomNo = 0; 1618 time_t now; 1619 1620 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 1621 walker = start; 1622 while (walker->next != end) { // go through every atom and count 1623 walker = walker->next; 1624 AtomNo++; 1625 } 1626 if (out != NULL) { 1627 *out << AtomNo << "\n\tCreated by molecuilder on " << ctime(&now); 1628 1628 walker = start; 1629 1629 while (walker->next != end) { // go through every atom of this element … … 1631 1631 walker->OutputXYZLine(out); 1632 1632 } 1633 1634 1635 1633 return true; 1634 } else 1635 return false; 1636 1636 }; 1637 1637 … … 1641 1641 void molecule::CountAtoms(ofstream *out) 1642 1642 { 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 Walker->nr = i;// update number in molecule (for easier referencing in FragmentMolecule lateron)1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1643 int i = 0; 1644 atom *Walker = start; 1645 while (Walker->next != end) { 1646 Walker = Walker->next; 1647 i++; 1648 } 1649 if ((AtomCount == 0) || (i != AtomCount)) { 1650 *out << Verbose(3) << "Mismatch in AtomCount " << AtomCount << " and recounted number " << i << ", renaming all." << endl; 1651 AtomCount = i; 1652 1653 // count NonHydrogen atoms and give each atom a unique name 1654 if (AtomCount != 0) { 1655 i=0; 1656 NoNonHydrogen = 0; 1657 Walker = start; 1658 while (Walker->next != end) { 1659 Walker = Walker->next; 1660 Walker->nr = i; // update number in molecule (for easier referencing in FragmentMolecule lateron) 1661 if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it 1662 NoNonHydrogen++; 1663 Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name"); 1664 Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name"); 1665 sprintf(Walker->Name, "%2s%02d", Walker->type->symbol, Walker->nr+1); 1666 *out << "Naming atom nr. " << Walker->nr << " " << Walker->Name << "." << endl; 1667 i++; 1668 } 1669 } else 1670 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 1671 } 1672 1672 }; 1673 1673 … … 1676 1676 void molecule::CountElements() 1677 1677 { 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1678 int i = 0; 1679 for(i=MAX_ELEMENTS;i--;) 1680 ElementsInMolecule[i] = 0; 1681 ElementCount = 0; 1682 1683 atom *walker = start; 1684 while (walker->next != end) { 1685 walker = walker->next; 1686 ElementsInMolecule[walker->type->Z]++; 1687 i++; 1688 } 1689 for(i=MAX_ELEMENTS;i--;) 1690 ElementCount += (ElementsInMolecule[i] != 0 ? 1 : 0); 1691 1691 }; 1692 1692 … … 1698 1698 int molecule::CountCyclicBonds(ofstream *out) 1699 1699 { 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1700 int No = 0; 1701 int *MinimumRingSize = NULL; 1702 MoleculeLeafClass *Subgraphs = NULL; 1703 class StackClass<bond *> *BackEdgeStack = NULL; 1704 bond *Binder = first; 1705 if ((Binder->next != last) && (Binder->next->Type == Undetermined)) { 1706 *out << Verbose(0) << "No Depth-First-Search analysis performed so far, calling ..." << endl; 1707 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack); 1708 while (Subgraphs->next != NULL) { 1709 Subgraphs = Subgraphs->next; 1710 delete(Subgraphs->previous); 1711 } 1712 delete(Subgraphs); 1713 delete[](MinimumRingSize); 1714 } 1715 while(Binder->next != last) { 1716 Binder = Binder->next; 1717 if (Binder->Cyclic) 1718 No++; 1719 } 1720 delete(BackEdgeStack); 1721 return No; 1722 1722 }; 1723 1723 /** Returns Shading as a char string. … … 1727 1727 string molecule::GetColor(enum Shading color) 1728 1728 { 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1729 switch(color) { 1730 case white: 1731 return "white"; 1732 break; 1733 case lightgray: 1734 return "lightgray"; 1735 break; 1736 case darkgray: 1737 return "darkgray"; 1738 break; 1739 case black: 1740 return "black"; 1741 break; 1742 default: 1743 return "uncolored"; 1744 break; 1745 }; 1746 1746 }; 1747 1747 … … 1752 1752 void molecule::CalculateOrbitals(class config &configuration) 1753 1753 { 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1754 configuration.MaxPsiDouble = configuration.PsiMaxNoDown = configuration.PsiMaxNoUp = configuration.PsiType = 0; 1755 for(int i=MAX_ELEMENTS;i--;) { 1756 if (ElementsInMolecule[i] != 0) { 1757 //cout << "CalculateOrbitals: " << elemente->FindElement(i)->name << " has a valence of " << (int)elemente->FindElement(i)->Valence << " and there are " << ElementsInMolecule[i] << " of it." << endl; 1758 configuration.MaxPsiDouble += ElementsInMolecule[i]*((int)elemente->FindElement(i)->Valence); 1759 } 1760 } 1761 configuration.PsiMaxNoDown = configuration.MaxPsiDouble/2 + (configuration.MaxPsiDouble % 2); 1762 configuration.PsiMaxNoUp = configuration.MaxPsiDouble/2; 1763 configuration.MaxPsiDouble /= 2; 1764 configuration.PsiType = (configuration.PsiMaxNoDown == configuration.PsiMaxNoUp) ? 0 : 1; 1765 if ((configuration.PsiType == 1) && (configuration.ProcPEPsi < 2)) { 1766 configuration.ProcPEGamma /= 2; 1767 configuration.ProcPEPsi *= 2; 1768 } else { 1769 configuration.ProcPEGamma *= configuration.ProcPEPsi; 1770 configuration.ProcPEPsi = 1; 1771 } 1772 configuration.InitMaxMinStopStep = configuration.MaxMinStopStep = configuration.MaxPsiDouble; 1773 1773 }; 1774 1774 … … 1779 1779 { 1780 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 1781 // 1 We will parse bonds out of the dbond file created by tremolo. 1782 int atom1, atom2, temp; 1783 atom *Walker, *OtherWalker; 1784 1785 if (!input) 1786 { 1787 cout << Verbose(1) << "Opening silica failed \n"; 1788 }; 1789 1790 *input >> ws >> atom1; 1791 *input >> ws >> atom2; 1792 cout << Verbose(1) << "Scanning file\n"; 1793 while (!input->eof()) // Check whether we read everything already 1794 { 1795 *input >> ws >> atom1; 1796 *input >> ws >> atom2; 1797 if(atom2<atom1) //Sort indices of atoms in order 1798 { 1799 temp=atom1; 1800 atom1=atom2; 1801 atom2=temp; 1802 }; 1803 1804 Walker=start; 1805 while(Walker-> nr != atom1) // Find atom corresponding to first index 1806 { 1807 Walker = Walker->next; 1808 }; 1809 OtherWalker = Walker->next; 1810 while(OtherWalker->nr != atom2) // Find atom corresponding to second index 1811 { 1812 OtherWalker= OtherWalker->next; 1813 }; 1814 AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices. 1815 1816 } 1817 1818 CreateListOfBondsPerAtom(out); 1819 1819 1820 1820 }; … … 1827 1827 * To make it O(N log N) the function uses the linked-cell technique as follows: 1828 1828 * The procedure is step-wise: 1829 * 1830 * 1831 * 1832 * 1833 * 1834 * 1835 * 1836 * 1829 * -# Remove every bond in list 1830 * -# Count the atoms in the molecule with CountAtoms() 1831 * -# partition cell into smaller linked cells of size \a bonddistance 1832 * -# put each atom into its corresponding cell 1833 * -# go through every cell, check the atoms therein against all possible bond partners in the 27 adjacent cells, add bond if true 1834 * -# create the list of bonds via CreateListOfBondsPerAtom() 1835 * -# correct the bond degree iteratively (single->double->triple bond) 1836 * -# finally print the bond list to \a *out if desired 1837 1837 * \param *out out stream for printing the matrix, NULL if no output 1838 1838 * \param bonddistance length of linked cells (i.e. maximum minimal length checked) … … 1842 1842 { 1843 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 if ((first->next != last) && (last->previous != first)) {// there are bonds present1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 //*out << Verbose(1) << "divisor[" << i << "]= " << divisor[i] << "." << endl;1871 1872 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 if (CellList[index] == NULL)// allocate molecule if not done1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 while (Walker->next != CellList[Index]->end) {// go through every atom1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 if (CellList[index] != NULL) {// if there are any atoms in this cell1926 1927 while(OtherWalker->next != CellList[index]->end) {// go through every atom in this cell1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 AddBond(Walker->father, OtherWalker->father, 1);// also increases molecule::BondCount1940 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 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 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 1844 atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL; 1845 int No, NoBonds, CandidateBondNo; 1846 int NumberCells, divisor[NDIM], n[NDIM], N[NDIM], index, Index, j; 1847 molecule **CellList; 1848 double distance, MinDistance, MaxDistance; 1849 double *matrix = ReturnFullMatrixforSymmetric(cell_size); 1850 Vector x; 1851 int FalseBondDegree = 0; 1852 1853 BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem); 1854 *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl; 1855 // remove every bond from the list 1856 if ((first->next != last) && (last->previous != first)) { // there are bonds present 1857 cleanup(first,last); 1858 } 1859 1860 // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering) 1861 CountAtoms(out); 1862 *out << Verbose(1) << "AtomCount " << AtomCount << "." << endl; 1863 1864 if (AtomCount != 0) { 1865 // 1. find divisor for each axis, such that a sphere with radius of at least bonddistance can be placed into each cell 1866 j=-1; 1867 for (int i=0;i<NDIM;i++) { 1868 j += i+1; 1869 divisor[i] = (int)floor(cell_size[j]/bonddistance); // take smaller value such that size of linked cell is at least bonddistance 1870 //*out << Verbose(1) << "divisor[" << i << "] = " << divisor[i] << "." << endl; 1871 } 1872 // 2a. allocate memory for the cell list 1873 NumberCells = divisor[0]*divisor[1]*divisor[2]; 1874 *out << Verbose(1) << "Allocating " << NumberCells << " cells." << endl; 1875 CellList = (molecule **) Malloc(sizeof(molecule *)*NumberCells, "molecule::CreateAdjacencyList - ** CellList"); 1876 for (int i=NumberCells;i--;) 1877 CellList[i] = NULL; 1878 1879 // 2b. put all atoms into its corresponding list 1880 Walker = start; 1881 while(Walker->next != end) { 1882 Walker = Walker->next; 1883 //*out << Verbose(1) << "Current atom is " << *Walker << " with coordinates "; 1884 //Walker->x.Output(out); 1885 //*out << "." << endl; 1886 // compute the cell by the atom's coordinates 1887 j=-1; 1888 for (int i=0;i<NDIM;i++) { 1889 j += i+1; 1890 x.CopyVector(&(Walker->x)); 1891 x.KeepPeriodic(out, matrix); 1892 n[i] = (int)floor(x.x[i]/cell_size[j]*(double)divisor[i]); 1893 } 1894 index = n[2] + (n[1] + n[0] * divisor[1]) * divisor[2]; 1895 //*out << Verbose(1) << "Atom " << *Walker << " goes into cell number [" << n[0] << "," << n[1] << "," << n[2] << "] = " << index << "." << endl; 1896 // add copy atom to this cell 1897 if (CellList[index] == NULL) // allocate molecule if not done 1898 CellList[index] = new molecule(elemente); 1899 OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference 1900 //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl; 1901 } 1902 //for (int i=0;i<NumberCells;i++) 1903 //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl; 1904 1905 1906 // 3a. go through every cell 1907 for (N[0]=divisor[0];N[0]--;) 1908 for (N[1]=divisor[1];N[1]--;) 1909 for (N[2]=divisor[2];N[2]--;) { 1910 Index = N[2] + (N[1] + N[0] * divisor[1]) * divisor[2]; 1911 if (CellList[Index] != NULL) { // if there atoms in this cell 1912 //*out << Verbose(1) << "Current cell is " << Index << "." << endl; 1913 // 3b. for every atom therein 1914 Walker = CellList[Index]->start; 1915 while (Walker->next != CellList[Index]->end) { // go through every atom 1916 Walker = Walker->next; 1917 //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl; 1918 // 3c. check for possible bond between each atom in this and every one in the 27 cells 1919 for (n[0]=-1;n[0]<=1;n[0]++) 1920 for (n[1]=-1;n[1]<=1;n[1]++) 1921 for (n[2]=-1;n[2]<=1;n[2]++) { 1922 // compute the index of this comparison cell and make it periodic 1923 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]; 1924 //*out << Verbose(1) << "Number of comparison cell is " << index << "." << endl; 1925 if (CellList[index] != NULL) { // if there are any atoms in this cell 1926 OtherWalker = CellList[index]->start; 1927 while(OtherWalker->next != CellList[index]->end) { // go through every atom in this cell 1928 OtherWalker = OtherWalker->next; 1929 //*out << Verbose(0) << "Current comparison atom is " << *OtherWalker << "." << endl; 1930 /// \todo periodic check is missing here! 1931 //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl; 1932 MinDistance = OtherWalker->type->CovalentRadius + Walker->type->CovalentRadius; 1933 MinDistance *= (IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem; 1934 MaxDistance = MinDistance + BONDTHRESHOLD; 1935 MinDistance -= BONDTHRESHOLD; 1936 distance = OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size); 1937 if ((OtherWalker->father->nr > Walker->father->nr) && (distance <= MaxDistance*MaxDistance) && (distance >= MinDistance*MinDistance)) { // create bond if distance is smaller 1938 //*out << Verbose(1) << "Adding Bond between " << *Walker << " and " << *OtherWalker << " in distance " << sqrt(distance) << "." << endl; 1939 AddBond(Walker->father, OtherWalker->father, 1); // also increases molecule::BondCount 1940 } else { 1941 //*out << Verbose(1) << "Not Adding: Wrong label order or distance too great." << endl; 1942 } 1943 } 1944 } 1945 } 1946 } 1947 } 1948 } 1949 1950 1951 1952 // 4. free the cell again 1953 for (int i=NumberCells;i--;) 1954 if (CellList[i] != NULL) { 1955 delete(CellList[i]); 1956 } 1957 Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList"); 1958 1959 // create the adjacency list per atom 1960 CreateListOfBondsPerAtom(out); 1961 1962 // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees, 1963 // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene 1964 // preferred over carbon bonds). Beforehand, we had picked the first mismatching partner, which lead to oxygenes with single instead of 1965 // double bonds as was expected. 1966 if (BondCount != 0) { 1967 NoCyclicBonds = 0; 1968 *out << Verbose(1) << "Correcting Bond degree of each bond ... "; 1969 do { 1970 No = 0; // No acts as breakup flag (if 1 we still continue) 1971 Walker = start; 1972 while (Walker->next != end) { // go through every atom 1973 Walker = Walker->next; 1974 // count valence of first partner 1975 NoBonds = 0; 1976 for(j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) 1977 NoBonds += ListOfBondsPerAtom[Walker->nr][j]->BondDegree; 1978 *out << Verbose(3) << "Walker " << *Walker << ": " << (int)Walker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl; 1979 if ((int)(Walker->type->NoValenceOrbitals) > NoBonds) { // we have a mismatch, check all bonding partners for mismatch 1980 Candidate = NULL; 1981 CandidateBondNo = -1; 1982 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through each of its bond partners 1983 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 1984 // count valence of second partner 1985 NoBonds = 0; 1986 for(j=0;j<NumberOfBondsPerAtom[OtherWalker->nr];j++) 1987 NoBonds += ListOfBondsPerAtom[OtherWalker->nr][j]->BondDegree; 1988 *out << Verbose(3) << "OtherWalker " << *OtherWalker << ": " << (int)OtherWalker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl; 1989 if ((int)(OtherWalker->type->NoValenceOrbitals) > NoBonds) { // check if possible candidate 1990 if ((Candidate == NULL) || (NumberOfBondsPerAtom[Candidate->nr] > NumberOfBondsPerAtom[OtherWalker->nr])) { // pick the one with fewer number of bonds first 1991 Candidate = OtherWalker; 1992 CandidateBondNo = i; 1993 *out << Verbose(3) << "New candidate is " << *Candidate << "." << endl; 1994 } 1995 } 1996 } 1997 if ((Candidate != NULL) && (CandidateBondNo != -1)) { 1998 ListOfBondsPerAtom[Walker->nr][CandidateBondNo]->BondDegree++; 1999 *out << Verbose(2) << "Increased bond degree for bond " << *ListOfBondsPerAtom[Walker->nr][CandidateBondNo] << "." << endl; 2000 } else 2001 *out << Verbose(2) << "Could not find correct degree for atom " << *Walker << "." << endl; 2002 FalseBondDegree++; 2003 } 2004 } 2005 } while (No); 2006 *out << " done." << endl; 2007 } else 2008 *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl; 2009 *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl; 2010 2011 // output bonds for debugging (if bond chain list was correctly installed) 2012 *out << Verbose(1) << endl << "From contents of bond chain list:"; 2013 bond *Binder = first; 2014 while(Binder->next != last) { 2015 Binder = Binder->next; 2016 *out << *Binder << "\t" << endl; 2017 } 2018 *out << endl; 2019 } else 2020 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl; 2021 *out << Verbose(0) << "End of CreateAdjacencyList." << endl; 2022 Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix"); 2023 2023 2024 2024 }; … … 2036 2036 MoleculeLeafClass * molecule::DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack) 2037 2037 { 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 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 2099 2100 } while (1);// (3)2101 2102 2103 2104 2105 2106 } while (1);// (2)2107 2108 2109 2110 2111 2112 2113 2114 2115 // (6)(Ancestor of Walker is not Root)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 if (!BackStepping) {// coming from (8) want to go to (3)2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 // (11) Root is separation vertex,set Walker to Root and go to (4)2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 *out << " ===";2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2038 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount); 2039 BackEdgeStack = new StackClass<bond *> (BondCount); 2040 MoleculeLeafClass *SubGraphs = new MoleculeLeafClass(NULL); 2041 MoleculeLeafClass *LeafWalker = SubGraphs; 2042 int CurrentGraphNr = 0, OldGraphNr; 2043 int ComponentNumber = 0; 2044 atom *Walker = NULL, *OtherAtom = NULL, *Root = start->next; 2045 bond *Binder = NULL; 2046 bool BackStepping = false; 2047 2048 *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl; 2049 2050 ResetAllBondsToUnused(); 2051 ResetAllAtomNumbers(); 2052 InitComponentNumbers(); 2053 BackEdgeStack->ClearStack(); 2054 while (Root != end) { // if there any atoms at all 2055 // (1) mark all edges unused, empty stack, set atom->GraphNr = 0 for all 2056 AtomStack->ClearStack(); 2057 2058 // put into new subgraph molecule and add this to list of subgraphs 2059 LeafWalker = new MoleculeLeafClass(LeafWalker); 2060 LeafWalker->Leaf = new molecule(elemente); 2061 LeafWalker->Leaf->AddCopyAtom(Root); 2062 2063 OldGraphNr = CurrentGraphNr; 2064 Walker = Root; 2065 do { // (10) 2066 do { // (2) set number and Lowpoint of Atom to i, increase i, push current atom 2067 if (!BackStepping) { // if we don't just return from (8) 2068 Walker->GraphNr = CurrentGraphNr; 2069 Walker->LowpointNr = CurrentGraphNr; 2070 *out << Verbose(1) << "Setting Walker[" << Walker->Name << "]'s number to " << Walker->GraphNr << " with Lowpoint " << Walker->LowpointNr << "." << endl; 2071 AtomStack->Push(Walker); 2072 CurrentGraphNr++; 2073 } 2074 do { // (3) if Walker has no unused egdes, go to (5) 2075 BackStepping = false; // reset backstepping flag for (8) 2076 if (Binder == NULL) // if we don't just return from (11), Binder is already set to next unused 2077 Binder = FindNextUnused(Walker); 2078 if (Binder == NULL) 2079 break; 2080 *out << Verbose(2) << "Current Unused Bond is " << *Binder << "." << endl; 2081 // (4) Mark Binder used, ... 2082 Binder->MarkUsed(black); 2083 OtherAtom = Binder->GetOtherAtom(Walker); 2084 *out << Verbose(2) << "(4) OtherAtom is " << OtherAtom->Name << "." << endl; 2085 if (OtherAtom->GraphNr != -1) { 2086 // (4a) ... if "other" atom has been visited (GraphNr != 0), set lowpoint to minimum of both, go to (3) 2087 Binder->Type = BackEdge; 2088 BackEdgeStack->Push(Binder); 2089 Walker->LowpointNr = ( Walker->LowpointNr < OtherAtom->GraphNr ) ? Walker->LowpointNr : OtherAtom->GraphNr; 2090 *out << Verbose(3) << "(4a) Visited: Setting Lowpoint of Walker[" << Walker->Name << "] to " << Walker->LowpointNr << "." << endl; 2091 } else { 2092 // (4b) ... otherwise set OtherAtom as Ancestor of Walker and Walker as OtherAtom, go to (2) 2093 Binder->Type = TreeEdge; 2094 OtherAtom->Ancestor = Walker; 2095 Walker = OtherAtom; 2096 *out << Verbose(3) << "(4b) Not Visited: OtherAtom[" << OtherAtom->Name << "]'s Ancestor is now " << OtherAtom->Ancestor->Name << ", Walker is OtherAtom " << OtherAtom->Name << "." << endl; 2097 break; 2098 } 2099 Binder = NULL; 2100 } while (1); // (3) 2101 if (Binder == NULL) { 2102 *out << Verbose(2) << "No more Unused Bonds." << endl; 2103 break; 2104 } else 2105 Binder = NULL; 2106 } while (1); // (2) 2107 2108 // 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! 2109 if ((Walker == Root) && (Binder == NULL)) 2110 break; 2111 2112 // (5) if Ancestor of Walker is ... 2113 *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl; 2114 if (Walker->Ancestor->GraphNr != Root->GraphNr) { 2115 // (6) (Ancestor of Walker is not Root) 2116 if (Walker->LowpointNr < Walker->Ancestor->GraphNr) { 2117 // (6a) set Ancestor's Lowpoint number to minimum of of its Ancestor and itself, go to Step(8) 2118 Walker->Ancestor->LowpointNr = (Walker->Ancestor->LowpointNr < Walker->LowpointNr) ? Walker->Ancestor->LowpointNr : Walker->LowpointNr; 2119 *out << Verbose(2) << "(6) Setting Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s Lowpoint to " << Walker->Ancestor->LowpointNr << "." << endl; 2120 } else { 2121 // (7) (Ancestor of Walker is a separating vertex, remove all from stack till Walker (including), these and Ancestor form a component 2122 Walker->Ancestor->SeparationVertex = true; 2123 *out << Verbose(2) << "(7) Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s is a separating vertex, creating component." << endl; 2124 SetNextComponentNumber(Walker->Ancestor, ComponentNumber); 2125 *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Ancestor's Compont is " << ComponentNumber << "." << endl; 2126 SetNextComponentNumber(Walker, ComponentNumber); 2127 *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Compont is " << ComponentNumber << "." << endl; 2128 do { 2129 OtherAtom = AtomStack->PopLast(); 2130 LeafWalker->Leaf->AddCopyAtom(OtherAtom); 2131 SetNextComponentNumber(OtherAtom, ComponentNumber); 2132 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl; 2133 } while (OtherAtom != Walker); 2134 ComponentNumber++; 2135 } 2136 // (8) Walker becomes its Ancestor, go to (3) 2137 *out << Verbose(2) << "(8) Walker[" << Walker->Name << "] is now its Ancestor " << Walker->Ancestor->Name << ", backstepping. " << endl; 2138 Walker = Walker->Ancestor; 2139 BackStepping = true; 2140 } 2141 if (!BackStepping) { // coming from (8) want to go to (3) 2142 // (9) remove all from stack till Walker (including), these and Root form a component 2143 AtomStack->Output(out); 2144 SetNextComponentNumber(Root, ComponentNumber); 2145 *out << Verbose(3) << "(9) Root[" << Root->Name << "]'s Component is " << ComponentNumber << "." << endl; 2146 SetNextComponentNumber(Walker, ComponentNumber); 2147 *out << Verbose(3) << "(9) Walker[" << Walker->Name << "]'s Component is " << ComponentNumber << "." << endl; 2148 do { 2149 OtherAtom = AtomStack->PopLast(); 2150 LeafWalker->Leaf->AddCopyAtom(OtherAtom); 2151 SetNextComponentNumber(OtherAtom, ComponentNumber); 2152 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl; 2153 } while (OtherAtom != Walker); 2154 ComponentNumber++; 2155 2156 // (11) Root is separation vertex, set Walker to Root and go to (4) 2157 Walker = Root; 2158 Binder = FindNextUnused(Walker); 2159 *out << Verbose(1) << "(10) Walker is Root[" << Root->Name << "], next Unused Bond is " << Binder << "." << endl; 2160 if (Binder != NULL) { // Root is separation vertex 2161 *out << Verbose(1) << "(11) Root is a separation vertex." << endl; 2162 Walker->SeparationVertex = true; 2163 } 2164 } 2165 } while ((BackStepping) || (Binder != NULL)); // (10) halt only if Root has no unused edges 2166 2167 // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph 2168 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2169 LeafWalker->Leaf->Output(out); 2170 *out << endl; 2171 2172 // step on to next root 2173 while ((Root != end) && (Root->GraphNr != -1)) { 2174 //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl; 2175 if (Root->GraphNr != -1) // if already discovered, step on 2176 Root = Root->next; 2177 } 2178 } 2179 // set cyclic bond criterium on "same LP" basis 2180 Binder = first; 2181 while(Binder->next != last) { 2182 Binder = Binder->next; 2183 if (Binder->rightatom->LowpointNr == Binder->leftatom->LowpointNr) { // cyclic ?? 2184 Binder->Cyclic = true; 2185 NoCyclicBonds++; 2186 } 2187 } 2188 2189 2190 *out << Verbose(1) << "Final graph info for each atom is:" << endl; 2191 Walker = start; 2192 while (Walker->next != end) { 2193 Walker = Walker->next; 2194 *out << Verbose(2) << "Atom " << Walker->Name << " is " << ((Walker->SeparationVertex) ? "a" : "not a") << " separation vertex, components are "; 2195 OutputComponentNumber(out, Walker); 2196 *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl; 2197 } 2198 2199 *out << Verbose(1) << "Final graph info for each bond is:" << endl; 2200 Binder = first; 2201 while(Binder->next != last) { 2202 Binder = Binder->next; 2203 *out << Verbose(2) << ((Binder->Type == TreeEdge) ? "TreeEdge " : "BackEdge ") << *Binder << ": <"; 2204 *out << ((Binder->leftatom->SeparationVertex) ? "SP," : "") << "L" << Binder->leftatom->LowpointNr << " G" << Binder->leftatom->GraphNr << " Comp."; 2205 OutputComponentNumber(out, Binder->leftatom); 2206 *out << " === "; 2207 *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp."; 2208 OutputComponentNumber(out, Binder->rightatom); 2209 *out << ">." << endl; 2210 if (Binder->Cyclic) // cyclic ?? 2211 *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl; 2212 } 2213 2214 // free all and exit 2215 delete(AtomStack); 2216 *out << Verbose(0) << "End of DepthFirstSearchAnalysis" << endl; 2217 return SubGraphs; 2218 2218 }; 2219 2219 … … 2228 2228 * \todo BFS from the not-same-LP to find back to starting point of tributary cycle over more than one bond 2229 2229 */ 2230 void molecule::CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> * 2231 { 2232 2233 2234 2235 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount);// will hold the current ring2236 class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount);// contains all "touched" atoms (that need to be reset after BFS loop)2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 BFSStack->ClearStack();// start with empty BFS stack2261 2262 2263 2264 2265 do {// look for Root2266 2267 2268 2269 2270 2271 2230 void molecule::CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> * BackEdgeStack, int *&MinimumRingSize) 2231 { 2232 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CyclicStructureAnalysis: **PredecessorList"); 2233 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList"); 2234 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList"); 2235 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount); // will hold the current ring 2236 class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount); // contains all "touched" atoms (that need to be reset after BFS loop) 2237 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL; 2238 bond *Binder = NULL, *BackEdge = NULL; 2239 int RingSize, NumCycles, MinRingSize = -1; 2240 2241 // initialise each vertex as white with no predecessor, empty queue, color Root lightgray 2242 for (int i=AtomCount;i--;) { 2243 PredecessorList[i] = NULL; 2244 ShortestPathList[i] = -1; 2245 ColorList[i] = white; 2246 } 2247 2248 *out << Verbose(1) << "Back edge list - "; 2249 BackEdgeStack->Output(out); 2250 2251 *out << Verbose(1) << "Analysing cycles ... " << endl; 2252 NumCycles = 0; 2253 while (!BackEdgeStack->IsEmpty()) { 2254 BackEdge = BackEdgeStack->PopFirst(); 2255 // this is the target 2256 Root = BackEdge->leftatom; 2257 // this is the source point 2258 Walker = BackEdge->rightatom; 2259 ShortestPathList[Walker->nr] = 0; 2260 BFSStack->ClearStack(); // start with empty BFS stack 2261 BFSStack->Push(Walker); 2262 TouchedStack->Push(Walker); 2263 *out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl; 2264 OtherAtom = NULL; 2265 do { // look for Root 2266 Walker = BFSStack->PopFirst(); 2267 *out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl; 2268 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 2269 Binder = ListOfBondsPerAtom[Walker->nr][i]; 2270 if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder) 2271 OtherAtom = Binder->GetOtherAtom(Walker); 2272 2272 #ifdef ADDHYDROGEN 2273 2273 if (OtherAtom->type->Z != 1) { 2274 2274 #endif 2275 2276 2277 2278 2279 PredecessorList[OtherAtom->nr] = Walker;// Walker is the predecessor2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2275 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 2276 if (ColorList[OtherAtom->nr] == white) { 2277 TouchedStack->Push(OtherAtom); 2278 ColorList[OtherAtom->nr] = lightgray; 2279 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 2280 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 2281 *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; 2282 //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance 2283 *out << Verbose(3) << "Putting OtherAtom into queue." << endl; 2284 BFSStack->Push(OtherAtom); 2285 //} 2286 } else { 2287 *out << Verbose(3) << "Not Adding, has already been visited." << endl; 2288 } 2289 if (OtherAtom == Root) 2290 break; 2291 2291 #ifdef ADDHYDROGEN 2292 2293 2294 2295 2292 } else { 2293 *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl; 2294 ColorList[OtherAtom->nr] = black; 2295 } 2296 2296 #endif 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 if (!OtherAtom->GetTrueFather()->IsCyclic)// if one bond in the loop is not marked as cyclic, we haven't found this cycle yet2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 TouchedStack->Push(OtherAtom);// last was wrongly popped2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 *out << Walker->Name << "with a length of " << RingSize << "." << endl << endl;2344 2345 2346 2347 2348 2349 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 BFSStack->ClearStack();// start with empty BFS stack2376 2377 2378 2379 2380 while (OtherAtom != NULL) {// look for Root2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 PredecessorList[OtherAtom->nr] = Walker;// Walker is the predecessor2392 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 2422 2423 2424 2425 2426 2427 2428 2297 } else { 2298 *out << Verbose(2) << "Bond " << *Binder << " not Visiting, is the back edge." << endl; 2299 } 2300 } 2301 ColorList[Walker->nr] = black; 2302 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2303 if (OtherAtom == Root) { // if we have found the root, check whether this cycle wasn't already found beforehand 2304 // step through predecessor list 2305 while (OtherAtom != BackEdge->rightatom) { 2306 if (!OtherAtom->GetTrueFather()->IsCyclic) // if one bond in the loop is not marked as cyclic, we haven't found this cycle yet 2307 break; 2308 else 2309 OtherAtom = PredecessorList[OtherAtom->nr]; 2310 } 2311 if (OtherAtom == BackEdge->rightatom) { // if each atom in found cycle is cyclic, loop's been found before already 2312 *out << Verbose(3) << "This cycle was already found before, skipping and removing seeker from search." << endl;\ 2313 do { 2314 OtherAtom = TouchedStack->PopLast(); 2315 if (PredecessorList[OtherAtom->nr] == Walker) { 2316 *out << Verbose(4) << "Removing " << *OtherAtom << " from lists and stacks." << endl; 2317 PredecessorList[OtherAtom->nr] = NULL; 2318 ShortestPathList[OtherAtom->nr] = -1; 2319 ColorList[OtherAtom->nr] = white; 2320 BFSStack->RemoveItem(OtherAtom); 2321 } 2322 } while ((!TouchedStack->IsEmpty()) && (PredecessorList[OtherAtom->nr] == NULL)); 2323 TouchedStack->Push(OtherAtom); // last was wrongly popped 2324 OtherAtom = BackEdge->rightatom; // set to not Root 2325 } else 2326 OtherAtom = Root; 2327 } 2328 } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]))); 2329 2330 if (OtherAtom == Root) { 2331 // now climb back the predecessor list and thus find the cycle members 2332 NumCycles++; 2333 RingSize = 1; 2334 Root->GetTrueFather()->IsCyclic = true; 2335 *out << Verbose(1) << "Found ring contains: "; 2336 Walker = Root; 2337 while (Walker != BackEdge->rightatom) { 2338 *out << Walker->Name << " <-> "; 2339 Walker = PredecessorList[Walker->nr]; 2340 Walker->GetTrueFather()->IsCyclic = true; 2341 RingSize++; 2342 } 2343 *out << Walker->Name << " with a length of " << RingSize << "." << endl << endl; 2344 // walk through all and set MinimumRingSize 2345 Walker = Root; 2346 MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize; 2347 while (Walker != BackEdge->rightatom) { 2348 Walker = PredecessorList[Walker->nr]; 2349 if (RingSize < MinimumRingSize[Walker->GetTrueFather()->nr]) 2350 MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize; 2351 } 2352 if ((RingSize < MinRingSize) || (MinRingSize == -1)) 2353 MinRingSize = RingSize; 2354 } else { 2355 *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl; 2356 } 2357 2358 // now clean the lists 2359 while (!TouchedStack->IsEmpty()){ 2360 Walker = TouchedStack->PopFirst(); 2361 PredecessorList[Walker->nr] = NULL; 2362 ShortestPathList[Walker->nr] = -1; 2363 ColorList[Walker->nr] = white; 2364 } 2365 } 2366 if (MinRingSize != -1) { 2367 // go over all atoms 2368 Root = start; 2369 while(Root->next != end) { 2370 Root = Root->next; 2371 2372 if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is 2373 Walker = Root; 2374 ShortestPathList[Walker->nr] = 0; 2375 BFSStack->ClearStack(); // start with empty BFS stack 2376 BFSStack->Push(Walker); 2377 TouchedStack->Push(Walker); 2378 //*out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl; 2379 OtherAtom = Walker; 2380 while (OtherAtom != NULL) { // look for Root 2381 Walker = BFSStack->PopFirst(); 2382 //*out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl; 2383 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 2384 Binder = ListOfBondsPerAtom[Walker->nr][i]; 2385 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 2386 OtherAtom = Binder->GetOtherAtom(Walker); 2387 //*out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 2388 if (ColorList[OtherAtom->nr] == white) { 2389 TouchedStack->Push(OtherAtom); 2390 ColorList[OtherAtom->nr] = lightgray; 2391 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 2392 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 2393 //*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; 2394 if (OtherAtom->GetTrueFather()->IsCyclic) { // if the other atom is connected to a ring 2395 MinimumRingSize[Root->GetTrueFather()->nr] = ShortestPathList[OtherAtom->nr]+MinimumRingSize[OtherAtom->GetTrueFather()->nr]; 2396 OtherAtom = NULL; //break; 2397 break; 2398 } else 2399 BFSStack->Push(OtherAtom); 2400 } else { 2401 //*out << Verbose(3) << "Not Adding, has already been visited." << endl; 2402 } 2403 } else { 2404 //*out << Verbose(3) << "Not Visiting, is a back edge." << endl; 2405 } 2406 } 2407 ColorList[Walker->nr] = black; 2408 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2409 } 2410 2411 // now clean the lists 2412 while (!TouchedStack->IsEmpty()){ 2413 Walker = TouchedStack->PopFirst(); 2414 PredecessorList[Walker->nr] = NULL; 2415 ShortestPathList[Walker->nr] = -1; 2416 ColorList[Walker->nr] = white; 2417 } 2418 } 2419 *out << Verbose(1) << "Minimum ring size of " << *Root << " is " << MinimumRingSize[Root->GetTrueFather()->nr] << "." << endl; 2420 } 2421 *out << Verbose(1) << "Minimum ring size is " << MinRingSize << ", over " << NumCycles << " cycles total." << endl; 2422 } else 2423 *out << Verbose(1) << "No rings were detected in the molecular structure." << endl; 2424 2425 Free((void **)&PredecessorList, "molecule::CyclicStructureAnalysis: **PredecessorList"); 2426 Free((void **)&ShortestPathList, "molecule::CyclicStructureAnalysis: **ShortestPathList"); 2427 Free((void **)&ColorList, "molecule::CyclicStructureAnalysis: **ColorList"); 2428 delete(BFSStack); 2429 2429 }; 2430 2430 … … 2436 2436 void molecule::SetNextComponentNumber(atom *vertex, int nr) 2437 2437 { 2438 2439 2440 2441 if (vertex->ComponentNr[i] == -1) {// check if not yet used2442 2443 2444 2445 2446 break;// breaking here will not cause error!2447 2448 2449 2450 2451 2438 int i=0; 2439 if (vertex != NULL) { 2440 for(;i<NumberOfBondsPerAtom[vertex->nr];i++) { 2441 if (vertex->ComponentNr[i] == -1) { // check if not yet used 2442 vertex->ComponentNr[i] = nr; 2443 break; 2444 } 2445 else if (vertex->ComponentNr[i] == nr) // if number is already present, don't add another time 2446 break; // breaking here will not cause error! 2447 } 2448 if (i == NumberOfBondsPerAtom[vertex->nr]) 2449 cerr << "Error: All Component entries are already occupied!" << endl; 2450 } else 2451 cerr << "Error: Given vertex is NULL!" << endl; 2452 2452 }; 2453 2453 … … 2457 2457 void molecule::OutputComponentNumber(ofstream *out, atom *vertex) 2458 2458 { 2459 2460 *out << vertex->ComponentNr[i] << "";2459 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2460 *out << vertex->ComponentNr[i] << " "; 2461 2461 }; 2462 2462 … … 2465 2465 void molecule::InitComponentNumbers() 2466 2466 { 2467 2468 2469 2470 2471 2472 2473 2474 2475 2467 atom *Walker = start; 2468 while(Walker->next != end) { 2469 Walker = Walker->next; 2470 if (Walker->ComponentNr != NULL) 2471 Free((void **)&Walker->ComponentNr, "molecule::InitComponentNumbers: **Walker->ComponentNr"); 2472 Walker->ComponentNr = (int *) Malloc(sizeof(int)*NumberOfBondsPerAtom[Walker->nr], "molecule::InitComponentNumbers: *Walker->ComponentNr"); 2473 for (int i=NumberOfBondsPerAtom[Walker->nr];i--;) 2474 Walker->ComponentNr[i] = -1; 2475 } 2476 2476 }; 2477 2477 … … 2482 2482 bond * molecule::FindNextUnused(atom *vertex) 2483 2483 { 2484 2485 2486 2487 2484 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2485 if (ListOfBondsPerAtom[vertex->nr][i]->IsUsed() == white) 2486 return(ListOfBondsPerAtom[vertex->nr][i]); 2487 return NULL; 2488 2488 }; 2489 2489 … … 2493 2493 void molecule::ResetAllBondsToUnused() 2494 2494 { 2495 2496 2497 2498 2499 2495 bond *Binder = first; 2496 while (Binder->next != last) { 2497 Binder = Binder->next; 2498 Binder->ResetUsed(); 2499 } 2500 2500 }; 2501 2501 … … 2504 2504 void molecule::ResetAllAtomNumbers() 2505 2505 { 2506 2507 2508 2509 Walker->GraphNr= -1;2510 2506 atom *Walker = start; 2507 while (Walker->next != end) { 2508 Walker = Walker->next; 2509 Walker->GraphNr = -1; 2510 } 2511 2511 }; 2512 2512 … … 2517 2517 void OutputAlreadyVisited(ofstream *out, int *list) 2518 2518 { 2519 2520 for(int i=1;i<=list[0];i++) *out << Verbose(0) << list[i] << "";2521 2519 *out << Verbose(4) << "Already Visited Bonds:\t"; 2520 for(int i=1;i<=list[0];i++) *out << Verbose(0) << list[i] << " "; 2521 *out << endl; 2522 2522 }; 2523 2523 … … 2525 2525 * The upper limit is 2526 2526 * \f[ 2527 * 2527 * n = N \cdot C^k 2528 2528 * \f] 2529 2529 * where \f$C=2^c\f$ and c is the maximum bond degree over N number of atoms. … … 2534 2534 int molecule::GuesstimateFragmentCount(ofstream *out, int order) 2535 2535 { 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2536 int c = 0; 2537 int FragmentCount; 2538 // get maximum bond degree 2539 atom *Walker = start; 2540 while (Walker->next != end) { 2541 Walker = Walker->next; 2542 c = (NumberOfBondsPerAtom[Walker->nr] > c) ? NumberOfBondsPerAtom[Walker->nr] : c; 2543 } 2544 FragmentCount = NoNonHydrogen*(1 << (c*order)); 2545 *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl; 2546 return FragmentCount; 2547 2547 }; 2548 2548 … … 2555 2555 bool molecule::ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet) 2556 2556 { 2557 2558 2559 2560 2561 2562 2563 2564 2565 CurrentSet.insert(AtomNr);// insert at end, hence in same order as in file!2566 2567 2568 2569 2570 2571 2572 2573 2574 2557 stringstream line; 2558 int AtomNr; 2559 int status = 0; 2560 2561 line.str(buffer); 2562 while (!line.eof()) { 2563 line >> AtomNr; 2564 if ((AtomNr >= 0) && (AtomNr < AtomCount)) { 2565 CurrentSet.insert(AtomNr); // insert at end, hence in same order as in file! 2566 status++; 2567 } // else it's "-1" or else and thus must not be added 2568 } 2569 *out << Verbose(1) << "The scanned KeySet is "; 2570 for(KeySet::iterator runner = CurrentSet.begin(); runner != CurrentSet.end(); runner++) { 2571 *out << (*runner) << "\t"; 2572 } 2573 *out << endl; 2574 return (status != 0); 2575 2575 }; 2576 2576 … … 2587 2587 bool molecule::ParseKeySetFile(ofstream *out, char *path, Graph *&FragmentList) 2588 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 if ((strlen(buffer) > 0) && (ScanBufferIntoKeySet(out, buffer, CurrentSet))) {// if at least one valid atom was added, write config2613 testGraphInsert = FragmentList->insert(GraphPair (CurrentSet,pair<int,double>(NumberOfFragments++,1)));// store fragment number and current factor2614 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 2589 bool status = true; 2590 ifstream InputFile; 2591 stringstream line; 2592 GraphTestPair testGraphInsert; 2593 int NumberOfFragments = 0; 2594 double TEFactor; 2595 char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename"); 2596 2597 if (FragmentList == NULL) { // check list pointer 2598 FragmentList = new Graph; 2599 } 2600 2601 // 1st pass: open file and read 2602 *out << Verbose(1) << "Parsing the KeySet file ... " << endl; 2603 sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, KEYSETFILE); 2604 InputFile.open(filename); 2605 if (InputFile != NULL) { 2606 // each line represents a new fragment 2607 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - *buffer"); 2608 // 1. parse keysets and insert into temp. graph 2609 while (!InputFile.eof()) { 2610 InputFile.getline(buffer, MAXSTRINGSIZE); 2611 KeySet CurrentSet; 2612 if ((strlen(buffer) > 0) && (ScanBufferIntoKeySet(out, buffer, CurrentSet))) { // if at least one valid atom was added, write config 2613 testGraphInsert = FragmentList->insert(GraphPair (CurrentSet,pair<int,double>(NumberOfFragments++,1))); // store fragment number and current factor 2614 if (!testGraphInsert.second) { 2615 cerr << "KeySet file must be corrupt as there are two equal key sets therein!" << endl; 2616 } 2617 } 2618 } 2619 // 2. Free and done 2620 InputFile.close(); 2621 InputFile.clear(); 2622 Free((void **)&buffer, "molecule::ParseKeySetFile - *buffer"); 2623 *out << Verbose(1) << "done." << endl; 2624 } else { 2625 *out << Verbose(1) << "File " << filename << " not found." << endl; 2626 status = false; 2627 } 2628 2629 // 2nd pass: open TEFactors file and read 2630 *out << Verbose(1) << "Parsing the TEFactors file ... " << endl; 2631 sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, TEFACTORSFILE); 2632 InputFile.open(filename); 2633 if (InputFile != NULL) { 2634 // 3. add found TEFactors to each keyset 2635 NumberOfFragments = 0; 2636 for(Graph::iterator runner = FragmentList->begin();runner != FragmentList->end(); runner++) { 2637 if (!InputFile.eof()) { 2638 InputFile >> TEFactor; 2639 (*runner).second.second = TEFactor; 2640 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl; 2641 } else { 2642 status = false; 2643 break; 2644 } 2645 } 2646 // 4. Free and done 2647 InputFile.close(); 2648 *out << Verbose(1) << "done." << endl; 2649 } else { 2650 *out << Verbose(1) << "File " << filename << " not found." << endl; 2651 status = false; 2652 } 2653 2654 // free memory 2655 Free((void **)&filename, "molecule::ParseKeySetFile - filename"); 2656 2657 return status; 2658 2658 }; 2659 2659 … … 2666 2666 bool molecule::StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path) 2667 2667 { 2668 2669 bool status =true;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 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2668 ofstream output; 2669 bool status = true; 2670 string line; 2671 2672 // open KeySet file 2673 line = path; 2674 line.append("/"); 2675 line += FRAGMENTPREFIX; 2676 line += KEYSETFILE; 2677 output.open(line.c_str(), ios::out); 2678 *out << Verbose(1) << "Saving key sets of the total graph ... "; 2679 if(output != NULL) { 2680 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) { 2681 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 2682 if (sprinter != (*runner).first.begin()) 2683 output << "\t"; 2684 output << *sprinter; 2685 } 2686 output << endl; 2687 } 2688 *out << "done." << endl; 2689 } else { 2690 cerr << "Unable to open " << line << " for writing keysets!" << endl; 2691 status = false; 2692 } 2693 output.close(); 2694 output.clear(); 2695 2696 // open TEFactors file 2697 line = path; 2698 line.append("/"); 2699 line += FRAGMENTPREFIX; 2700 line += TEFACTORSFILE; 2701 output.open(line.c_str(), ios::out); 2702 *out << Verbose(1) << "Saving TEFactors of the total graph ... "; 2703 if(output != NULL) { 2704 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) 2705 output << (*runner).second.second << endl; 2706 *out << Verbose(1) << "done." << endl; 2707 } else { 2708 *out << Verbose(1) << "failed to open " << line << "." << endl; 2709 status = false; 2710 } 2711 output.close(); 2712 2713 return status; 2714 2714 }; 2715 2715 … … 2722 2722 bool molecule::StoreAdjacencyToFile(ofstream *out, char *path) 2723 2723 { 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2724 ofstream AdjacencyFile; 2725 atom *Walker = NULL; 2726 stringstream line; 2727 bool status = true; 2728 2729 line << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE; 2730 AdjacencyFile.open(line.str().c_str(), ios::out); 2731 *out << Verbose(1) << "Saving adjacency list ... "; 2732 if (AdjacencyFile != NULL) { 2733 Walker = start; 2734 while(Walker->next != end) { 2735 Walker = Walker->next; 2736 AdjacencyFile << Walker->nr << "\t"; 2737 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) 2738 AdjacencyFile << ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker)->nr << "\t"; 2739 AdjacencyFile << endl; 2740 } 2741 AdjacencyFile.close(); 2742 *out << Verbose(1) << "done." << endl; 2743 } else { 2744 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl; 2745 status = false; 2746 } 2747 2748 return status; 2749 2749 }; 2750 2750 … … 2757 2757 bool molecule::CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms) 2758 2758 { 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 int NonMatchNumber = 0;// will number of atoms with differing bond structure2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2759 ifstream File; 2760 stringstream filename; 2761 bool status = true; 2762 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 2763 2764 filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE; 2765 File.open(filename.str().c_str(), ios::out); 2766 *out << Verbose(1) << "Looking at bond structure stored in adjacency file and comparing to present one ... "; 2767 if (File != NULL) { 2768 // allocate storage structure 2769 int NonMatchNumber = 0; // will number of atoms with differing bond structure 2770 int *CurrentBonds = (int *) Malloc(sizeof(int)*8, "molecule::CheckAdjacencyFileAgainstMolecule - CurrentBonds"); // contains parsed bonds of current atom 2771 int CurrentBondsOfAtom; 2772 2773 // Parse the file line by line and count the bonds 2774 while (!File.eof()) { 2775 File.getline(buffer, MAXSTRINGSIZE); 2776 stringstream line; 2777 line.str(buffer); 2778 int AtomNr = -1; 2779 line >> AtomNr; 2780 CurrentBondsOfAtom = -1; // we count one too far due to line end 2781 // parse into structure 2782 if ((AtomNr >= 0) && (AtomNr < AtomCount)) { 2783 while (!line.eof()) 2784 line >> CurrentBonds[ ++CurrentBondsOfAtom ]; 2785 // compare against present bonds 2786 //cout << Verbose(2) << "Walker is " << *Walker << ", bond partners: "; 2787 if (CurrentBondsOfAtom == NumberOfBondsPerAtom[AtomNr]) { 2788 for(int i=0;i<NumberOfBondsPerAtom[AtomNr];i++) { 2789 int id = ListOfBondsPerAtom[AtomNr][i]->GetOtherAtom(ListOfAtoms[AtomNr])->nr; 2790 int j = 0; 2791 for (;(j<CurrentBondsOfAtom) && (CurrentBonds[j++] != id);); // check against all parsed bonds 2792 if (CurrentBonds[j-1] != id) { // no match ? Then mark in ListOfAtoms 2793 ListOfAtoms[AtomNr] = NULL; 2794 NonMatchNumber++; 2795 status = false; 2796 //out << "[" << id << "]\t"; 2797 } else { 2798 //out << id << "\t"; 2799 } 2800 } 2801 //out << endl; 2802 } else { 2803 *out << "Number of bonds for Atom " << *ListOfAtoms[AtomNr] << " does not match, parsed " << CurrentBondsOfAtom << " against " << NumberOfBondsPerAtom[AtomNr] << "." << endl; 2804 status = false; 2805 } 2806 } 2807 } 2808 File.close(); 2809 File.clear(); 2810 if (status) { // if equal we parse the KeySetFile 2811 *out << Verbose(1) << "done: Equal." << endl; 2812 status = true; 2813 } else 2814 *out << Verbose(1) << "done: Not equal by " << NonMatchNumber << " atoms." << endl; 2815 Free((void **)&CurrentBonds, "molecule::CheckAdjacencyFileAgainstMolecule - **CurrentBonds"); 2816 } else { 2817 *out << Verbose(1) << "Adjacency file not found." << endl; 2818 status = false; 2819 } 2820 *out << endl; 2821 Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 2822 2823 return status; 2824 2824 }; 2825 2825 … … 2835 2835 bool molecule::CheckOrderAtSite(ofstream *out, bool *AtomMask, Graph *GlobalKeySetList, int Order, int *MinimumRingSize, char *path) 2836 2836 { 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 if (AtomMask[AtomCount] == true)// break after one step2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 //*out << Verbose(2) << "Scanned " << lines-1 << " lines." << endl;// one endline too much2867 2868 2869 map<int, pair<double,int> > AdaptiveCriteriaList;// (Root No., (Value, Order)) !2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 No -= 1;// indices start at 1 in file, not 02885 2886 2887 2888 map<int,KeySet>::iterator marker = IndexKeySetList.find(No);// find keyset to Frag No.2889 if (marker != IndexKeySetList.end()) {// if found2890 Value *= 1 + MYEPSILON*(*((*marker).second.begin()));// in case of equal energies this makes em not equal without changing anything actually2891 2892 2893 2894 2895 if ((*PresentItem).second.second < FragOrder)// if order there is lower, update entry with higher-order term2896 //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)2897 {// if value is smaller, update value and order2898 2899 2900 *out << Verbose(2) << "Updated element (" <<(*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;2901 2902 *out << Verbose(2) << "Did not update element " <<(*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl;2903 2904 2905 *out << Verbose(2) << "Inserted element (" <<(*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 AtomMask[Walker->nr] = true;// include all (non-hydrogen) atoms2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 AtomMask[Walker->nr] = true;// include all (non-hydrogen) atoms2966 2967 2968 2969 2970 if ((Order == 0) && (AtomMask[AtomCount] == false))// single stepping, just check2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 *out << "";2983 2984 2985 2986 2987 2988 2989 2990 2837 atom *Walker = start; 2838 bool status = false; 2839 ifstream InputFile; 2840 2841 // initialize mask list 2842 for(int i=AtomCount;i--;) 2843 AtomMask[i] = false; 2844 2845 if (Order < 0) { // adaptive increase of BondOrder per site 2846 if (AtomMask[AtomCount] == true) // break after one step 2847 return false; 2848 // parse the EnergyPerFragment file 2849 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckOrderAtSite: *buffer"); 2850 sprintf(buffer, "%s/%s%s.dat", path, FRAGMENTPREFIX, ENERGYPERFRAGMENT); 2851 InputFile.open(buffer, ios::in); 2852 if ((InputFile != NULL) && (GlobalKeySetList != NULL)) { 2853 // transmorph graph keyset list into indexed KeySetList 2854 map<int,KeySet> IndexKeySetList; 2855 for(Graph::iterator runner = GlobalKeySetList->begin(); runner != GlobalKeySetList->end(); runner++) { 2856 IndexKeySetList.insert( pair<int,KeySet>(runner->second.first,runner->first) ); 2857 } 2858 int lines = 0; 2859 // count the number of lines, i.e. the number of fragments 2860 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines 2861 InputFile.getline(buffer, MAXSTRINGSIZE); 2862 while(!InputFile.eof()) { 2863 InputFile.getline(buffer, MAXSTRINGSIZE); 2864 lines++; 2865 } 2866 //*out << Verbose(2) << "Scanned " << lines-1 << " lines." << endl; // one endline too much 2867 InputFile.clear(); 2868 InputFile.seekg(ios::beg); 2869 map<int, pair<double,int> > AdaptiveCriteriaList; // (Root No., (Value, Order)) ! 2870 int No, FragOrder; 2871 double Value; 2872 // each line represents a fragment root (Atom::nr) id and its energy contribution 2873 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines 2874 InputFile.getline(buffer, MAXSTRINGSIZE); 2875 while(!InputFile.eof()) { 2876 InputFile.getline(buffer, MAXSTRINGSIZE); 2877 if (strlen(buffer) > 2) { 2878 //*out << Verbose(2) << "Scanning: " << buffer << endl; 2879 stringstream line(buffer); 2880 line >> FragOrder; 2881 line >> ws >> No; 2882 line >> ws >> Value; // skip time entry 2883 line >> ws >> Value; 2884 No -= 1; // indices start at 1 in file, not 0 2885 //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl; 2886 2887 // clean the list of those entries that have been superceded by higher order terms already 2888 map<int,KeySet>::iterator marker = IndexKeySetList.find(No); // find keyset to Frag No. 2889 if (marker != IndexKeySetList.end()) { // if found 2890 Value *= 1 + MYEPSILON*(*((*marker).second.begin())); // in case of equal energies this makes em not equal without changing anything actually 2891 // 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 2892 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) )); 2893 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 2894 if (!InsertedElement.second) { // this root is already present 2895 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term 2896 //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) 2897 { // if value is smaller, update value and order 2898 (*PresentItem).second.first = fabs(Value); 2899 (*PresentItem).second.second = FragOrder; 2900 *out << Verbose(2) << "Updated element (" << (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl; 2901 } else { 2902 *out << Verbose(2) << "Did not update element " << (*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl; 2903 } 2904 } else { 2905 *out << Verbose(2) << "Inserted element (" << (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl; 2906 } 2907 } else { 2908 *out << Verbose(1) << "No Fragment under No. " << No << "found." << endl; 2909 } 2910 } 2911 } 2912 // then map back onto (Value, (Root Nr., Order)) (i.e. sorted by value to pick the highest ones) 2913 map<double, pair<int,int> > FinalRootCandidates; 2914 *out << Verbose(1) << "Root candidate list is: " << endl; 2915 for(map<int, pair<double,int> >::iterator runner = AdaptiveCriteriaList.begin(); runner != AdaptiveCriteriaList.end(); runner++) { 2916 Walker = FindAtom((*runner).first); 2917 if (Walker != NULL) { 2918 //if ((*runner).second.second >= Walker->AdaptiveOrder) { // only insert if this is an "active" root site for the current order 2919 if (!Walker->MaxOrder) { 2920 *out << Verbose(2) << "(" << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "])" << endl; 2921 FinalRootCandidates.insert( make_pair( (*runner).second.first, pair<int,int>((*runner).first, (*runner).second.second) ) ); 2922 } else { 2923 *out << Verbose(2) << "Excluding (" << *Walker << ", " << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "]), as it has reached its maximum order." << endl; 2924 } 2925 } else { 2926 cerr << "Atom No. " << (*runner).second.first << " was not found in this molecule." << endl; 2927 } 2928 } 2929 // pick the ones still below threshold and mark as to be adaptively updated 2930 for(map<double, pair<int,int> >::iterator runner = FinalRootCandidates.upper_bound(pow(10.,Order)); runner != FinalRootCandidates.end(); runner++) { 2931 No = (*runner).second.first; 2932 Walker = FindAtom(No); 2933 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) { 2934 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 2935 AtomMask[No] = true; 2936 status = true; 2937 //} else 2938 //*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; 2939 } 2940 // close and done 2941 InputFile.close(); 2942 InputFile.clear(); 2943 } else { 2944 cerr << "Unable to parse " << buffer << " file, incrementing all." << endl; 2945 while (Walker->next != end) { 2946 Walker = Walker->next; 2947 #ifdef ADDHYDROGEN 2948 if (Walker->type->Z != 1) // skip hydrogen 2949 #endif 2950 { 2951 AtomMask[Walker->nr] = true; // include all (non-hydrogen) atoms 2952 status = true; 2953 } 2954 } 2955 } 2956 Free((void **)&buffer, "molecule::CheckOrderAtSite: *buffer"); 2957 // pick a given number of highest values and set AtomMask 2958 } else { // global increase of Bond Order 2959 while (Walker->next != end) { 2960 Walker = Walker->next; 2961 #ifdef ADDHYDROGEN 2962 if (Walker->type->Z != 1) // skip hydrogen 2963 #endif 2964 { 2965 AtomMask[Walker->nr] = true; // include all (non-hydrogen) atoms 2966 if ((Order != 0) && (Walker->AdaptiveOrder < Order)) // && (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr])) 2967 status = true; 2968 } 2969 } 2970 if ((Order == 0) && (AtomMask[AtomCount] == false)) // single stepping, just check 2971 status = true; 2972 2973 if (!status) { 2974 if (Order == 0) 2975 *out << Verbose(1) << "Single stepping done." << endl; 2976 else 2977 *out << Verbose(1) << "Order at every site is already equal or above desired order " << Order << "." << endl; 2978 } 2979 } 2980 2981 // print atom mask for debugging 2982 *out << " "; 2983 for(int i=0;i<AtomCount;i++) 2984 *out << (i % 10); 2985 *out << endl << "Atom mask is: "; 2986 for(int i=0;i<AtomCount;i++) 2987 *out << (AtomMask[i] ? "t" : "f"); 2988 *out << endl; 2989 2990 return status; 2991 2991 }; 2992 2992 … … 2998 2998 bool molecule::CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex) 2999 2999 { 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3000 element *runner = elemente->start; 3001 int AtomNo = 0; 3002 atom *Walker = NULL; 3003 3004 if (SortIndex != NULL) { 3005 *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl; 3006 return false; 3007 } 3008 SortIndex = (int *) Malloc(sizeof(int)*AtomCount, "molecule::FragmentMolecule: *SortIndex"); 3009 for(int i=AtomCount;i--;) 3010 SortIndex[i] = -1; 3011 while (runner->next != elemente->end) { // go through every element 3012 runner = runner->next; 3013 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 3014 Walker = start; 3015 while (Walker->next != end) { // go through every atom of this element 3016 Walker = Walker->next; 3017 if (Walker->type->Z == runner->Z) // if this atom fits to element 3018 SortIndex[Walker->nr] = AtomNo++; 3019 } 3020 } 3021 } 3022 return true; 3023 3023 }; 3024 3024 … … 3029 3029 y contribution", and that's why this consciously not done in the following loop) 3030 3030 * -# in a loop over all subgraphs 3031 * 3032 * 3031 * -# calls FragmentBOSSANOVA with this RootStack and within the subgraph molecule structure 3032 * -# creates molecule (fragment)s from the returned keysets (StoreFragmentFromKeySet) 3033 3033 * -# combines the generated molecule lists from all subgraphs 3034 3034 * -# saves to disk: fragment configs, adjacency, orderatsite, keyset files … … 3043 3043 int molecule::FragmentMolecule(ofstream *out, int Order, config *configuration) 3044 3044 { 3045 3046 3047 3048 3049 3050 MoleculeLeafClass *Subgraphs = NULL;// list of subgraphs from DFS analysis3051 3052 3053 3054 3055 3056 3057 Graph TotalGraph;// graph with all keysets however local numbers3058 3059 3060 3061 3062 3063 3045 MoleculeListClass *BondFragments = NULL; 3046 int *SortIndex = NULL; 3047 int *MinimumRingSize = new int[AtomCount]; 3048 int FragmentCounter; 3049 MoleculeLeafClass *MolecularWalker = NULL; 3050 MoleculeLeafClass *Subgraphs = NULL; // list of subgraphs from DFS analysis 3051 fstream File; 3052 bool FragmentationToDo = true; 3053 class StackClass<bond *> *BackEdgeStack = NULL, *LocalBackEdgeStack = NULL; 3054 bool CheckOrder = false; 3055 Graph **FragmentList = NULL; 3056 Graph *ParsedFragmentList = NULL; 3057 Graph TotalGraph; // graph with all keysets however local numbers 3058 int TotalNumberOfKeySets = 0; 3059 atom **ListOfAtoms = NULL; 3060 atom ***ListOfLocalAtoms = NULL; 3061 bool *AtomMask = NULL; 3062 3063 *out << endl; 3064 3064 #ifdef ADDHYDROGEN 3065 3065 *out << Verbose(0) << "I will treat hydrogen special and saturate dangling bonds with it." << endl; 3066 3066 #else 3067 3067 *out << Verbose(0) << "Hydrogen is treated just like the rest of the lot." << endl; 3068 3068 #endif 3069 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 Subgraphs->next->FillBondStructureFromReference(out, this, (FragmentCounter = 0), ListOfLocalAtoms, false);// we want to keep the created ListOfLocalAtoms3088 3089 3090 3091 3092 3093 3094 3095 3096 // 3097 // 3098 // 3099 // 3100 // 3101 // 3102 // 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 FragmentationToDo = false;// if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards3126 3127 3128 AtomMask[AtomCount] = true;// last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite()3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 //MolecularWalker->Leaf->OutputListOfBonds(out);// output ListOfBondsPerAtom for debugging3139 3140 3141 3142 3143 3144 3145 3146 FragmentCounter++;// next fragment list3147 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 //if (FragmentationToDo) {// we should always store the fragments again as coordination might have changed slightly without changing bond structure3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 //*out << Verbose(1) << "No fragments to store." << endl;3222 3223 3224 return ((int)(!FragmentationToDo)+1);// 1 - continue, 2 - stop (no fragmentation occured)3070 // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++ 3071 3072 // ===== 1. Check whether bond structure is same as stored in files ==== 3073 3074 // fill the adjacency list 3075 CreateListOfBondsPerAtom(out); 3076 3077 // create lookup table for Atom::nr 3078 FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount); 3079 3080 // === compare it with adjacency file === 3081 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 3082 Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms"); 3083 3084 // ===== 2. perform a DFS analysis to gather info on cyclic structure and a list of disconnected subgraphs ===== 3085 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack); 3086 // fill the bond structure of the individually stored subgraphs 3087 Subgraphs->next->FillBondStructureFromReference(out, this, (FragmentCounter = 0), ListOfLocalAtoms, false); // we want to keep the created ListOfLocalAtoms 3088 // analysis of the cycles (print rings, get minimum cycle length) for each subgraph 3089 for(int i=AtomCount;i--;) 3090 MinimumRingSize[i] = AtomCount; 3091 MolecularWalker = Subgraphs; 3092 FragmentCounter = 0; 3093 while (MolecularWalker->next != NULL) { 3094 MolecularWalker = MolecularWalker->next; 3095 LocalBackEdgeStack = new StackClass<bond *> (MolecularWalker->Leaf->BondCount); 3096 // // check the list of local atoms for debugging 3097 // *out << Verbose(0) << "ListOfLocalAtoms for this subgraph is:" << endl; 3098 // for (int i=0;i<AtomCount;i++) 3099 // if (ListOfLocalAtoms[FragmentCounter][i] == NULL) 3100 // *out << "\tNULL"; 3101 // else 3102 // *out << "\t" << ListOfLocalAtoms[FragmentCounter][i]->Name; 3103 *out << Verbose(0) << "Gathering local back edges for subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3104 MolecularWalker->Leaf->PickLocalBackEdges(out, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack); 3105 *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3106 MolecularWalker->Leaf->CyclicStructureAnalysis(out, LocalBackEdgeStack, MinimumRingSize); 3107 *out << Verbose(0) << "Done with Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3108 delete(LocalBackEdgeStack); 3109 } 3110 3111 // ===== 3. if structure still valid, parse key set file and others ===== 3112 FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList); 3113 3114 // ===== 4. check globally whether there's something to do actually (first adaptivity check) 3115 FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath); 3116 3117 // =================================== Begin of FRAGMENTATION =============================== 3118 // ===== 6a. assign each keyset to its respective subgraph ===== 3119 Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true); 3120 3121 // ===== 6b. prepare and go into the adaptive (Order<0), single-step (Order==0) or incremental (Order>0) cycle 3122 KeyStack *RootStack = new KeyStack[Subgraphs->next->Count()]; 3123 AtomMask = new bool[AtomCount+1]; 3124 AtomMask[AtomCount] = false; 3125 FragmentationToDo = false; // if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards 3126 while ((CheckOrder = CheckOrderAtSite(out, AtomMask, ParsedFragmentList, Order, MinimumRingSize, configuration->configpath))) { 3127 FragmentationToDo = FragmentationToDo || CheckOrder; 3128 AtomMask[AtomCount] = true; // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite() 3129 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 3130 Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0)); 3131 3132 // ===== 7. fill the bond fragment list ===== 3133 FragmentCounter = 0; 3134 MolecularWalker = Subgraphs; 3135 while (MolecularWalker->next != NULL) { 3136 MolecularWalker = MolecularWalker->next; 3137 *out << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl; 3138 //MolecularWalker->Leaf->OutputListOfBonds(out); // output ListOfBondsPerAtom for debugging 3139 if (MolecularWalker->Leaf->first->next != MolecularWalker->Leaf->last) { 3140 // call BOSSANOVA method 3141 *out << Verbose(0) << endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= " << endl; 3142 MolecularWalker->Leaf->FragmentBOSSANOVA(out, FragmentList[FragmentCounter], RootStack[FragmentCounter], MinimumRingSize); 3143 } else { 3144 cerr << "Subgraph " << MolecularWalker << " has no atoms!" << endl; 3145 } 3146 FragmentCounter++; // next fragment list 3147 } 3148 } 3149 delete[](RootStack); 3150 delete[](AtomMask); 3151 delete(ParsedFragmentList); 3152 delete[](MinimumRingSize); 3153 3154 3155 // ==================================== End of FRAGMENTATION ============================================ 3156 3157 // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf) 3158 Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph); 3159 3160 // free subgraph memory again 3161 FragmentCounter = 0; 3162 if (Subgraphs != NULL) { 3163 while (Subgraphs->next != NULL) { 3164 Subgraphs = Subgraphs->next; 3165 delete(FragmentList[FragmentCounter++]); 3166 delete(Subgraphs->previous); 3167 } 3168 delete(Subgraphs); 3169 } 3170 Free((void **)&FragmentList, "molecule::FragmentMolecule - **FragmentList"); 3171 3172 // ===== 8b. gather keyset lists (graphs) from all subgraphs and transform into MoleculeListClass ===== 3173 //if (FragmentationToDo) { // we should always store the fragments again as coordination might have changed slightly without changing bond structure 3174 // allocate memory for the pointer array and transmorph graphs into full molecular fragments 3175 BondFragments = new MoleculeListClass(); 3176 int k=0; 3177 for(Graph::iterator runner = TotalGraph.begin(); runner != TotalGraph.end(); runner++) { 3178 KeySet test = (*runner).first; 3179 *out << "Fragment No." << (*runner).second.first << " with TEFactor " << (*runner).second.second << "." << endl; 3180 BondFragments->insert(StoreFragmentFromKeySet(out, test, configuration)); 3181 k++; 3182 } 3183 *out << k << "/" << BondFragments->ListOfMolecules.size() << " fragments generated from the keysets." << endl; 3184 3185 // ===== 9. Save fragments' configuration and keyset files et al to disk === 3186 if (BondFragments->ListOfMolecules.size() != 0) { 3187 // create the SortIndex from BFS labels to order in the config file 3188 CreateMappingLabelsToConfigSequence(out, SortIndex); 3189 3190 *out << Verbose(1) << "Writing " << BondFragments->ListOfMolecules.size() << " possible bond fragmentation configs" << endl; 3191 if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex)) 3192 *out << Verbose(1) << "All configs written." << endl; 3193 else 3194 *out << Verbose(1) << "Some config writing failed." << endl; 3195 3196 // store force index reference file 3197 BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex); 3198 3199 // store keysets file 3200 StoreKeySetFile(out, TotalGraph, configuration->configpath); 3201 3202 // store Adjacency file 3203 StoreAdjacencyToFile(out, configuration->configpath); 3204 3205 // store Hydrogen saturation correction file 3206 BondFragments->AddHydrogenCorrection(out, configuration->configpath); 3207 3208 // store adaptive orders into file 3209 StoreOrderAtSiteFile(out, configuration->configpath); 3210 3211 // restore orbital and Stop values 3212 CalculateOrbitals(*configuration); 3213 3214 // free memory for bond part 3215 *out << Verbose(1) << "Freeing bond memory" << endl; 3216 delete(FragmentList); // remove bond molecule from memory 3217 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3218 } else 3219 *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl; 3220 //} else 3221 // *out << Verbose(1) << "No fragments to store." << endl; 3222 *out << Verbose(0) << "End of bond fragmentation." << endl; 3223 3224 return ((int)(!FragmentationToDo)+1); // 1 - continue, 2 - stop (no fragmentation occured) 3225 3225 }; 3226 3226 … … 3235 3235 bool molecule::PickLocalBackEdges(ofstream *out, atom **ListOfLocalAtoms, class StackClass<bond *> *&ReferenceStack, class StackClass<bond *> *&LocalStack) 3236 3236 { 3237 3238 3239 3240 3241 3242 3243 bond *FirstBond = Binder;// mark the first bond, so that we don't loop through the stack indefinitely3244 3245 3246 3247 do {// go through all bonds and push local ones3248 Walker = ListOfLocalAtoms[Binder->leftatom->nr];// get one atom in the reference molecule3249 3250 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {// go through the local list of bonds3251 3252 3253 3254 3255 3256 3257 3258 Binder = ReferenceStack->PopFirst();// loop the stack for next item3259 3260 3261 3262 3263 3237 bool status = true; 3238 if (ReferenceStack->IsEmpty()) { 3239 cerr << "ReferenceStack is empty!" << endl; 3240 return false; 3241 } 3242 bond *Binder = ReferenceStack->PopFirst(); 3243 bond *FirstBond = Binder; // mark the first bond, so that we don't loop through the stack indefinitely 3244 atom *Walker = NULL, *OtherAtom = NULL; 3245 ReferenceStack->Push(Binder); 3246 3247 do { // go through all bonds and push local ones 3248 Walker = ListOfLocalAtoms[Binder->leftatom->nr]; // get one atom in the reference molecule 3249 if (Walker != NULL) // if this Walker exists in the subgraph ... 3250 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through the local list of bonds 3251 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 3252 if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond 3253 LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]); 3254 *out << Verbose(3) << "Found local edge " << *(ListOfBondsPerAtom[Walker->nr][i]) << "." << endl; 3255 break; 3256 } 3257 } 3258 Binder = ReferenceStack->PopFirst(); // loop the stack for next item 3259 *out << Verbose(3) << "Current candidate edge " << Binder << "." << endl; 3260 ReferenceStack->Push(Binder); 3261 } while (FirstBond != Binder); 3262 3263 return status; 3264 3264 }; 3265 3265 … … 3272 3272 bool molecule::StoreOrderAtSiteFile(ofstream *out, char *path) 3273 3273 { 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3274 stringstream line; 3275 ofstream file; 3276 3277 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE; 3278 file.open(line.str().c_str()); 3279 *out << Verbose(1) << "Writing OrderAtSite " << ORDERATSITEFILE << " ... " << endl; 3280 if (file != NULL) { 3281 atom *Walker = start; 3282 while (Walker->next != end) { 3283 Walker = Walker->next; 3284 file << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << endl; 3285 *out << Verbose(2) << "Storing: " << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << "." << endl; 3286 } 3287 file.close(); 3288 *out << Verbose(1) << "done." << endl; 3289 return true; 3290 } else { 3291 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl; 3292 return false; 3293 } 3294 3294 }; 3295 3295 … … 3303 3303 bool molecule::ParseOrderAtSiteFromFile(ofstream *out, char *path) 3304 3304 { 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 if (AtomNr != -1) {// test whether we really parsed something (this is necessary, otherwise last atom is set twice and to 0 on second time)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 3305 unsigned char *OrderArray = (unsigned char *) Malloc(sizeof(unsigned char)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 3306 bool *MaxArray = (bool *) Malloc(sizeof(bool)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *MaxArray"); 3307 bool status; 3308 int AtomNr, value; 3309 stringstream line; 3310 ifstream file; 3311 3312 *out << Verbose(1) << "Begin of ParseOrderAtSiteFromFile" << endl; 3313 for(int i=AtomCount;i--;) 3314 OrderArray[i] = 0; 3315 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE; 3316 file.open(line.str().c_str()); 3317 if (file != NULL) { 3318 for (int i=AtomCount;i--;) { // initialise with 0 3319 OrderArray[i] = 0; 3320 MaxArray[i] = 0; 3321 } 3322 while (!file.eof()) { // parse from file 3323 AtomNr = -1; 3324 file >> AtomNr; 3325 if (AtomNr != -1) { // test whether we really parsed something (this is necessary, otherwise last atom is set twice and to 0 on second time) 3326 file >> value; 3327 OrderArray[AtomNr] = value; 3328 file >> value; 3329 MaxArray[AtomNr] = value; 3330 //*out << Verbose(2) << "AtomNr " << AtomNr << " with order " << (int)OrderArray[AtomNr] << " and max order set to " << (int)MaxArray[AtomNr] << "." << endl; 3331 } 3332 } 3333 atom *Walker = start; 3334 while (Walker->next != end) { // fill into atom classes 3335 Walker = Walker->next; 3336 Walker->AdaptiveOrder = OrderArray[Walker->nr]; 3337 Walker->MaxOrder = MaxArray[Walker->nr]; 3338 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl; 3339 } 3340 file.close(); 3341 *out << Verbose(1) << "done." << endl; 3342 status = true; 3343 } else { 3344 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl; 3345 status = false; 3346 } 3347 Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 3348 Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray"); 3349 3350 *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl; 3351 return status; 3352 3352 }; 3353 3353 … … 3360 3360 void molecule::CreateListOfBondsPerAtom(ofstream *out) 3361 3361 { 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3362 bond *Binder = NULL; 3363 atom *Walker = NULL; 3364 int TotalDegree; 3365 *out << Verbose(1) << "Begin of Creating ListOfBondsPerAtom: AtomCount = " << AtomCount << "\tBondCount = " << BondCount << "\tNoNonBonds = " << NoNonBonds << "." << endl; 3366 3367 // re-allocate memory 3368 *out << Verbose(2) << "(Re-)Allocating memory." << endl; 3369 if (ListOfBondsPerAtom != NULL) { 3370 for(int i=AtomCount;i--;) 3371 Free((void **)&ListOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom[i]"); 3372 Free((void **)&ListOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom"); 3373 } 3374 if (NumberOfBondsPerAtom != NULL) 3375 Free((void **)&NumberOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: NumberOfBondsPerAtom"); 3376 ListOfBondsPerAtom = (bond ***) Malloc(sizeof(bond **)*AtomCount, "molecule::CreateListOfBondsPerAtom: ***ListOfBondsPerAtom"); 3377 NumberOfBondsPerAtom = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfBondsPerAtom: *NumberOfBondsPerAtom"); 3378 3379 // reset bond counts per atom 3380 for(int i=AtomCount;i--;) 3381 NumberOfBondsPerAtom[i] = 0; 3382 // count bonds per atom 3383 Binder = first; 3384 while (Binder->next != last) { 3385 Binder = Binder->next; 3386 NumberOfBondsPerAtom[Binder->leftatom->nr]++; 3387 NumberOfBondsPerAtom[Binder->rightatom->nr]++; 3388 } 3389 for(int i=AtomCount;i--;) { 3390 // allocate list of bonds per atom 3391 ListOfBondsPerAtom[i] = (bond **) Malloc(sizeof(bond *)*NumberOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: **ListOfBondsPerAtom[]"); 3392 // clear the list again, now each NumberOfBondsPerAtom marks current free field 3393 NumberOfBondsPerAtom[i] = 0; 3394 } 3395 // fill the list 3396 Binder = first; 3397 while (Binder->next != last) { 3398 Binder = Binder->next; 3399 ListOfBondsPerAtom[Binder->leftatom->nr][NumberOfBondsPerAtom[Binder->leftatom->nr]++] = Binder; 3400 ListOfBondsPerAtom[Binder->rightatom->nr][NumberOfBondsPerAtom[Binder->rightatom->nr]++] = Binder; 3401 } 3402 3403 // output list for debugging 3404 *out << Verbose(3) << "ListOfBondsPerAtom for each atom:" << endl; 3405 Walker = start; 3406 while (Walker->next != end) { 3407 Walker = Walker->next; 3408 *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: "; 3409 TotalDegree = 0; 3410 for (int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) { 3411 *out << *ListOfBondsPerAtom[Walker->nr][j] << "\t"; 3412 TotalDegree += ListOfBondsPerAtom[Walker->nr][j]->BondDegree; 3413 } 3414 *out << " -- TotalDegree: " << TotalDegree << endl; 3415 } 3416 *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl; 3417 3417 }; 3418 3418 … … 3431 3431 void molecule::BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem) 3432 3432 { 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 if (AddedAtomList[Root->nr] == NULL)// add Root if not yet present3443 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 3469 3470 3471 3472 3473 PredecessorList[OtherAtom->nr] = Walker;// Walker is the predecessor3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 } 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)3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3433 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::BreadthFirstSearchAdd: **PredecessorList"); 3434 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::BreadthFirstSearchAdd: *ShortestPathList"); 3435 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::BreadthFirstSearchAdd: *ColorList"); 3436 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount); 3437 atom *Walker = NULL, *OtherAtom = NULL; 3438 bond *Binder = NULL; 3439 3440 // add Root if not done yet 3441 AtomStack->ClearStack(); 3442 if (AddedAtomList[Root->nr] == NULL) // add Root if not yet present 3443 AddedAtomList[Root->nr] = Mol->AddCopyAtom(Root); 3444 AtomStack->Push(Root); 3445 3446 // initialise each vertex as white with no predecessor, empty queue, color Root lightgray 3447 for (int i=AtomCount;i--;) { 3448 PredecessorList[i] = NULL; 3449 ShortestPathList[i] = -1; 3450 if (AddedAtomList[i] != NULL) // mark already present atoms (i.e. Root and maybe others) as visited 3451 ColorList[i] = lightgray; 3452 else 3453 ColorList[i] = white; 3454 } 3455 ShortestPathList[Root->nr] = 0; 3456 3457 // and go on ... Queue always contains all lightgray vertices 3458 while (!AtomStack->IsEmpty()) { 3459 // we have to pop the oldest atom from stack. This keeps the atoms on the stack always of the same ShortestPath distance. 3460 // 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 3461 // append length of 3 (their neighbours). Thus on stack we have always atoms of a certain length n at bottom of stack and 3462 // followed by n+1 till top of stack. 3463 Walker = AtomStack->PopFirst(); // pop oldest added 3464 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl; 3465 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 3466 Binder = ListOfBondsPerAtom[Walker->nr][i]; 3467 if (Binder != NULL) { // don't look at bond equal NULL 3468 OtherAtom = Binder->GetOtherAtom(Walker); 3469 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 3470 if (ColorList[OtherAtom->nr] == white) { 3471 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) 3472 ColorList[OtherAtom->nr] = lightgray; 3473 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 3474 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 3475 *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; 3476 if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance 3477 *out << Verbose(3); 3478 if (AddedAtomList[OtherAtom->nr] == NULL) { // add if it's not been so far 3479 AddedAtomList[OtherAtom->nr] = Mol->AddCopyAtom(OtherAtom); 3480 *out << "Added OtherAtom " << OtherAtom->Name; 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 *out << " and bond " << *(AddedBondList[Binder->nr]) << ", "; 3485 } 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) 3486 *out << "Not adding OtherAtom " << OtherAtom->Name; 3487 if (AddedBondList[Binder->nr] == NULL) { 3488 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3489 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3490 AddedBondList[Binder->nr]->Type = Binder->Type; 3491 *out << ", added Bond " << *(AddedBondList[Binder->nr]); 3492 } else 3493 *out << ", not added Bond "; 3494 } 3495 *out << ", putting OtherAtom into queue." << endl; 3496 AtomStack->Push(OtherAtom); 3497 } else { // out of bond order, then replace 3498 if ((AddedAtomList[OtherAtom->nr] == NULL) && (Binder->Cyclic)) 3499 ColorList[OtherAtom->nr] = white; // unmark if it has not been queued/added, to make it available via its other bonds (cyclic) 3500 if (Binder == Bond) 3501 *out << Verbose(3) << "Not Queueing, is the Root bond"; 3502 else if (ShortestPathList[OtherAtom->nr] >= BondOrder) 3503 *out << Verbose(3) << "Not Queueing, is out of Bond Count of " << BondOrder; 3504 if (!Binder->Cyclic) 3505 *out << ", is not part of a cyclic bond, saturating bond with Hydrogen." << endl; 3506 if (AddedBondList[Binder->nr] == NULL) { 3507 if ((AddedAtomList[OtherAtom->nr] != NULL)) { // .. whether we add or saturate 3508 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3509 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3510 AddedBondList[Binder->nr]->Type = Binder->Type; 3511 } else { 3512 3512 #ifdef ADDHYDROGEN 3513 3514 3513 if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem)) 3514 exit(1); 3515 3515 #endif 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3516 } 3517 } 3518 } 3519 } else { 3520 *out << Verbose(3) << "Not Adding, has already been visited." << endl; 3521 // This has to be a cyclic bond, check whether it's present ... 3522 if (AddedBondList[Binder->nr] == NULL) { 3523 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 3524 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3525 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3526 AddedBondList[Binder->nr]->Type = Binder->Type; 3527 } else { // if it's root bond it has to broken (otherwise we would not create the fragments) 3528 3528 #ifdef ADDHYDROGEN 3529 3530 3529 if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem)) 3530 exit(1); 3531 3531 #endif 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3532 } 3533 } 3534 } 3535 } 3536 } 3537 ColorList[Walker->nr] = black; 3538 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 3539 } 3540 Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList"); 3541 Free((void **)&ShortestPathList, "molecule::BreadthFirstSearchAdd: **ShortestPathList"); 3542 Free((void **)&ColorList, "molecule::BreadthFirstSearchAdd: **ColorList"); 3543 delete(AtomStack); 3544 3544 }; 3545 3545 … … 3555 3555 bool molecule::BuildInducedSubgraph(ofstream *out, const molecule *Father) 3556 3556 { 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 *out << Verbose(4) << "Son["<< Walker->father->nr <<"] of " << Walker->father <<" is " << ParentList[Walker->father->nr] << "." << endl;3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3557 atom *Walker = NULL, *OtherAtom = NULL; 3558 bool status = true; 3559 atom **ParentList = (atom **) Malloc(sizeof(atom *)*Father->AtomCount, "molecule::BuildInducedSubgraph: **ParentList"); 3560 3561 *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl; 3562 3563 // reset parent list 3564 *out << Verbose(3) << "Resetting ParentList." << endl; 3565 for (int i=Father->AtomCount;i--;) 3566 ParentList[i] = NULL; 3567 3568 // fill parent list with sons 3569 *out << Verbose(3) << "Filling Parent List." << endl; 3570 Walker = start; 3571 while (Walker->next != end) { 3572 Walker = Walker->next; 3573 ParentList[Walker->father->nr] = Walker; 3574 // Outputting List for debugging 3575 *out << Verbose(4) << "Son["<< Walker->father->nr <<"] of " << Walker->father << " is " << ParentList[Walker->father->nr] << "." << endl; 3576 } 3577 3578 // check each entry of parent list and if ok (one-to-and-onto matching) create bonds 3579 *out << Verbose(3) << "Creating bonds." << endl; 3580 Walker = Father->start; 3581 while (Walker->next != Father->end) { 3582 Walker = Walker->next; 3583 if (ParentList[Walker->nr] != NULL) { 3584 if (ParentList[Walker->nr]->father != Walker) { 3585 status = false; 3586 } else { 3587 for (int i=0;i<Father->NumberOfBondsPerAtom[Walker->nr];i++) { 3588 OtherAtom = Father->ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 3589 if (ParentList[OtherAtom->nr] != NULL) { // if otheratom is also a father of an atom on this molecule, create the bond 3590 *out << Verbose(4) << "Endpoints of Bond " << Father->ListOfBondsPerAtom[Walker->nr][i] << " are both present: " << ParentList[Walker->nr]->Name << " and " << ParentList[OtherAtom->nr]->Name << "." << endl; 3591 AddBond(ParentList[Walker->nr], ParentList[OtherAtom->nr], Father->ListOfBondsPerAtom[Walker->nr][i]->BondDegree); 3592 } 3593 } 3594 } 3595 } 3596 } 3597 3598 Free((void **)&ParentList, "molecule::BuildInducedSubgraph: **ParentList"); 3599 *out << Verbose(2) << "End of BuildInducedSubgraph." << endl; 3600 return status; 3601 3601 }; 3602 3602 … … 3610 3610 int molecule::LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList) 3611 3611 { 3612 3613 3614 3615 3616 SP = -1; //0;// not -1, so that Root is never removed3617 3618 3619 3620 3621 if (ShortestPathList[(*runner)] > SP) {// remove the oldest one with longest shortest path3622 3623 3624 3625 3626 3627 3612 atom *Runner = NULL; 3613 int SP, Removal; 3614 3615 *out << Verbose(2) << "Looking for removal candidate." << endl; 3616 SP = -1; //0; // not -1, so that Root is never removed 3617 Removal = -1; 3618 for (KeySet::iterator runner = Leaf->begin(); runner != Leaf->end(); runner++) { 3619 Runner = FindAtom((*runner)); 3620 if (Runner->type->Z != 1) { // skip all those added hydrogens when re-filling snake stack 3621 if (ShortestPathList[(*runner)] > SP) { // remove the oldest one with longest shortest path 3622 SP = ShortestPathList[(*runner)]; 3623 Removal = (*runner); 3624 } 3625 } 3626 } 3627 return Removal; 3628 3628 }; 3629 3629 … … 3638 3638 molecule * molecule::StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem) 3639 3639 { 3640 3641 3642 3643 3644 3645 3646 // 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 FatherOfRunner = FindAtom((*runner));// find the id3660 3661 3662 3663 3664 3665 // 3666 3667 3668 3669 3670 3671 if (SonList[FatherOfRunner->nr] != NULL) {// check if this, our father, is present in list3672 3673 3674 3675 // 3676 3677 // 3678 3679 // 3680 // 3681 3682 // 3683 3684 3685 // 3686 3687 3688 3689 // 3640 atom *Runner = NULL, *FatherOfRunner = NULL, *OtherFather = NULL; 3641 atom **SonList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::StoreFragmentFromStack: **SonList"); 3642 molecule *Leaf = new molecule(elemente); 3643 bool LonelyFlag = false; 3644 int size; 3645 3646 // *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl; 3647 3648 Leaf->BondDistance = BondDistance; 3649 for(int i=NDIM*2;i--;) 3650 Leaf->cell_size[i] = cell_size[i]; 3651 3652 // initialise SonList (indicates when we need to replace a bond with hydrogen instead) 3653 for(int i=AtomCount;i--;) 3654 SonList[i] = NULL; 3655 3656 // first create the minimal set of atoms from the KeySet 3657 size = 0; 3658 for(KeySet::iterator runner = Leaflet.begin(); runner != Leaflet.end(); runner++) { 3659 FatherOfRunner = FindAtom((*runner)); // find the id 3660 SonList[FatherOfRunner->nr] = Leaf->AddCopyAtom(FatherOfRunner); 3661 size++; 3662 } 3663 3664 // create the bonds between all: Make it an induced subgraph and add hydrogen 3665 // *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl; 3666 Runner = Leaf->start; 3667 while (Runner->next != Leaf->end) { 3668 Runner = Runner->next; 3669 LonelyFlag = true; 3670 FatherOfRunner = Runner->father; 3671 if (SonList[FatherOfRunner->nr] != NULL) { // check if this, our father, is present in list 3672 // create all bonds 3673 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father 3674 OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner); 3675 // *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather; 3676 if (SonList[OtherFather->nr] != NULL) { 3677 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 3678 if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba) 3679 // *out << Verbose(3) << "Adding Bond: "; 3680 // *out << 3681 Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree); 3682 // *out << "." << endl; 3683 //NumBonds[Runner->nr]++; 3684 } else { 3685 // *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl; 3686 } 3687 LonelyFlag = false; 3688 } else { 3689 // *out << ", who has no son in this fragment molecule." << endl; 3690 3690 #ifdef ADDHYDROGEN 3691 3692 3693 3691 //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl; 3692 if(!Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem)) 3693 exit(1); 3694 3694 #endif 3695 3696 3697 3698 3699 3700 3701 3702 3703 3695 //NumBonds[Runner->nr] += ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree; 3696 } 3697 } 3698 } else { 3699 *out << Verbose(0) << "ERROR: Son " << Runner->Name << " has father " << FatherOfRunner->Name << " but its entry in SonList is " << SonList[FatherOfRunner->nr] << "!" << endl; 3700 } 3701 if ((LonelyFlag) && (size > 1)) { 3702 *out << Verbose(0) << *Runner << "has got bonds only to hydrogens!" << endl; 3703 } 3704 3704 #ifdef ADDHYDROGEN 3705 3706 3705 while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen 3706 Runner = Runner->next; 3707 3707 #endif 3708 3709 3710 3711 3712 // 3713 3708 } 3709 Leaf->CreateListOfBondsPerAtom(out); 3710 //Leaflet->Leaf->ScanForPeriodicCorrection(out); 3711 Free((void **)&SonList, "molecule::StoreFragmentFromStack: **SonList"); 3712 // *out << Verbose(1) << "End of StoreFragmentFromKeyset." << endl; 3713 return Leaf; 3714 3714 }; 3715 3715 … … 3717 3717 */ 3718 3718 struct UniqueFragments { 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3719 config *configuration; 3720 atom *Root; 3721 Graph *Leaflet; 3722 KeySet *FragmentSet; 3723 int ANOVAOrder; 3724 int FragmentCounter; 3725 int CurrentIndex; 3726 double TEFactor; 3727 int *ShortestPathList; 3728 bool **UsedList; 3729 bond **BondsPerSPList; 3730 int *BondsPerSPCount; 3731 3731 }; 3732 3732 3733 3733 /** From a given set of Bond sorted by Shortest Path distance, create all possible fragments of size \a SetDimension. 3734 3734 * -# loops over every possible combination (2^dimension of edge set) 3735 * 3736 * 3735 * -# inserts current set, if there's still space left 3736 * -# yes: calls SPFragmentGenerator with structure, created new edge list and size respective to root dist 3737 3737 ance+1 3738 * 3739 * 3738 * -# no: stores fragment into keyset list by calling InsertFragmentIntoGraph 3739 * -# removes all items added into the snake stack (in UniqueFragments structure) added during level (root 3740 3740 distance) and current set 3741 3741 * \param *out output stream for debugging … … 3747 3747 void molecule::SPFragmentGenerator(ofstream *out, struct UniqueFragments *FragmentSearch, int RootDistance, bond **BondsSet, int SetDimension, int SubOrder) 3748 3748 { 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 *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;3769 3770 3771 3772 for (TouchedIndex=SubOrder+1;TouchedIndex--;)// empty touched list3773 3774 3775 3776 3777 3778 for (int i=1;i<NumCombinations;i++) {// sweep through all power set combinations (skip empty set!)3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 for (int j=0;j<SetDimension;j++) {// pull out every bit by shifting3789 bit = ((i & (1 << j)) != 0);// mask the bit for the j-th bond3790 if (bit) {// if bit is set, we add this bond partner3791 OtherWalker = BondsSet[j]->rightatom;// rightatom is always the one more distant, i.e. the one to add3792 3793 3794 3795 3796 TouchedList[TouchedIndex++] = OtherWalker->nr;// note as added3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 if (SubOrder > 1) {// Due to Added above we have to check extra whether we're not already reaching beyond the desired Order3812 3813 SP = RootDistance+1;// this is the next level3814 3815 3816 Binder = FragmentSearch->BondsPerSPList[2*SP];// start node for this level3817 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) {// compare to end node of this level3818 3819 3820 if (Binder->Contains(TouchedList[k]))// if we added this very endpiece3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 if (Binder->leftatom->nr == TouchedList[k])// leftatom is always the close one3832 3833 3834 3835 3836 3837 3838 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 3749 atom *OtherWalker = NULL; 3750 int verbosity = 0; //FragmentSearch->ANOVAOrder-SubOrder; 3751 int NumCombinations; 3752 bool bit; 3753 int bits, TouchedIndex, SubSetDimension, SP, Added; 3754 int Removal; 3755 int SpaceLeft; 3756 int *TouchedList = (int *) Malloc(sizeof(int)*(SubOrder+1), "molecule::SPFragmentGenerator: *TouchedList"); 3757 bond *Binder = NULL; 3758 bond **BondsList = NULL; 3759 KeySetTestPair TestKeySetInsert; 3760 3761 NumCombinations = 1 << SetDimension; 3762 3763 // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen 3764 // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder 3765 // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden 3766 3767 *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl; 3768 *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; 3769 3770 // initialised touched list (stores added atoms on this level) 3771 *out << Verbose(1+verbosity) << "Clearing touched list." << endl; 3772 for (TouchedIndex=SubOrder+1;TouchedIndex--;) // empty touched list 3773 TouchedList[TouchedIndex] = -1; 3774 TouchedIndex = 0; 3775 3776 // create every possible combination of the endpieces 3777 *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl; 3778 for (int i=1;i<NumCombinations;i++) { // sweep through all power set combinations (skip empty set!) 3779 // count the set bit of i 3780 bits = 0; 3781 for (int j=SetDimension;j--;) 3782 bits += (i & (1 << j)) >> j; 3783 3784 *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl; 3785 if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue 3786 // --1-- add this set of the power set of bond partners to the snake stack 3787 Added = 0; 3788 for (int j=0;j<SetDimension;j++) { // pull out every bit by shifting 3789 bit = ((i & (1 << j)) != 0); // mask the bit for the j-th bond 3790 if (bit) { // if bit is set, we add this bond partner 3791 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add 3792 //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl; 3793 *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl; 3794 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 3795 if (TestKeySetInsert.second) { 3796 TouchedList[TouchedIndex++] = OtherWalker->nr; // note as added 3797 Added++; 3798 } else { 3799 *out << Verbose(2+verbosity) << "This was item was already present in the keyset." << endl; 3800 } 3801 //FragmentSearch->UsedList[OtherWalker->nr][i] = true; 3802 //} 3803 } else { 3804 *out << Verbose(2+verbosity) << "Not adding." << endl; 3805 } 3806 } 3807 3808 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore 3809 if (SpaceLeft > 0) { 3810 *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl; 3811 if (SubOrder > 1) { // Due to Added above we have to check extra whether we're not already reaching beyond the desired Order 3812 // --2-- look at all added end pieces of this combination, construct bond subsets and sweep through a power set of these by recursion 3813 SP = RootDistance+1; // this is the next level 3814 // first count the members in the subset 3815 SubSetDimension = 0; 3816 Binder = FragmentSearch->BondsPerSPList[2*SP]; // start node for this level 3817 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) { // compare to end node of this level 3818 Binder = Binder->next; 3819 for (int k=TouchedIndex;k--;) { 3820 if (Binder->Contains(TouchedList[k])) // if we added this very endpiece 3821 SubSetDimension++; 3822 } 3823 } 3824 // then allocate and fill the list 3825 BondsList = (bond **) Malloc(sizeof(bond *)*SubSetDimension, "molecule::SPFragmentGenerator: **BondsList"); 3826 SubSetDimension = 0; 3827 Binder = FragmentSearch->BondsPerSPList[2*SP]; 3828 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) { 3829 Binder = Binder->next; 3830 for (int k=0;k<TouchedIndex;k++) { 3831 if (Binder->leftatom->nr == TouchedList[k]) // leftatom is always the close one 3832 BondsList[SubSetDimension++] = Binder; 3833 } 3834 } 3835 *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl; 3836 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 3837 Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList"); 3838 } 3839 } else { 3840 // --2-- otherwise store the complete fragment 3841 *out << Verbose(1+verbosity) << "Enough items on stack for a fragment!" << endl; 3842 // store fragment as a KeySet 3843 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: "; 3844 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3845 *out << (*runner) << " "; 3846 *out << endl; 3847 //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet)) 3848 //*out << Verbose(0) << "ERROR: The found fragment is not a connected subgraph!" << endl; 3849 InsertFragmentIntoGraph(out, FragmentSearch); 3850 //Removal = LookForRemovalCandidate(out, FragmentSearch->FragmentSet, FragmentSearch->ShortestPathList); 3851 //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration); 3852 } 3853 3854 // --3-- remove all added items in this level from snake stack 3855 *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl; 3856 for(int j=0;j<TouchedIndex;j++) { 3857 Removal = TouchedList[j]; 3858 *out << Verbose(2+verbosity) << "Removing item nr. " << Removal << " from snake stack." << endl; 3859 FragmentSearch->FragmentSet->erase(Removal); 3860 TouchedList[j] = -1; 3861 } 3862 *out << Verbose(2) << "Remaining local nr.s on snake stack are: "; 3863 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3864 *out << (*runner) << " "; 3865 *out << endl; 3866 TouchedIndex = 0; // set Index to 0 for list of atoms added on this level 3867 } else { 3868 *out << Verbose(2+verbosity) << "More atoms to add for this set (" << bits << ") than space left on stack " << SubOrder << ", skipping this set." << endl; 3869 } 3870 } 3871 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 3872 *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl; 3873 3873 }; 3874 3874 … … 3881 3881 bool molecule::CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment) 3882 3882 { 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 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 3883 atom *Walker = NULL, *Walker2 = NULL; 3884 bool BondStatus = false; 3885 int size; 3886 3887 *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl; 3888 *out << Verbose(2) << "Disconnected atom: "; 3889 3890 // count number of atoms in graph 3891 size = 0; 3892 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) 3893 size++; 3894 if (size > 1) 3895 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) { 3896 Walker = FindAtom(*runner); 3897 BondStatus = false; 3898 for(KeySet::iterator runners = Fragment->begin(); runners != Fragment->end(); runners++) { 3899 Walker2 = FindAtom(*runners); 3900 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) { 3901 if (ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker) == Walker2) { 3902 BondStatus = true; 3903 break; 3904 } 3905 if (BondStatus) 3906 break; 3907 } 3908 } 3909 if (!BondStatus) { 3910 *out << (*Walker) << endl; 3911 return false; 3912 } 3913 } 3914 else { 3915 *out << "none." << endl; 3916 return true; 3917 } 3918 *out << "none." << endl; 3919 3920 *out << Verbose(1) << "End of CheckForConnectedSubgraph" << endl; 3921 3922 return true; 3923 3923 } 3924 3924 … … 3940 3940 int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet) 3941 3941 { 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 CurrentEdge = FragmentSearch.BondsPerSPList[2*SP];/// start of this SP level's list3983 while (CurrentEdge->next != FragmentSearch.BondsPerSPList[2*SP+1]) {/// end of this SP level's list3984 3985 3986 Walker = CurrentEdge->rightatom;// rightatom is always the one more distant3987 Predecessor = CurrentEdge->leftatom;// ... and leftatom is predecessor3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 ) {// skip hydrogens and restrict to fragment4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 for(int i=1;i<Order;i++) {// skip the root edge in the printing4025 4026 4027 4028 4029 4030 4031 4032 4033 // creating fragments with the found edge sets(may be done in reverse order, faster)4034 SP = -1;// the Root <-> Root edge must be subtracted!4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next;// on SP level 0 there's only the root bond4051 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 4081 4082 4083 3942 int SP, AtomKeyNr; 3943 atom *Walker = NULL, *OtherWalker = NULL, *Predecessor = NULL; 3944 bond *Binder = NULL; 3945 bond *CurrentEdge = NULL; 3946 bond **BondsList = NULL; 3947 int RootKeyNr = FragmentSearch.Root->GetTrueFather()->nr; 3948 int Counter = FragmentSearch.FragmentCounter; 3949 int RemainingWalkers; 3950 3951 *out << endl; 3952 *out << Verbose(0) << "Begin of PowerSetGenerator with order " << Order << " at Root " << *FragmentSearch.Root << "." << endl; 3953 3954 // prepare Label and SP arrays of the BFS search 3955 FragmentSearch.ShortestPathList[FragmentSearch.Root->nr] = 0; 3956 3957 // prepare root level (SP = 0) and a loop bond denoting Root 3958 for (int i=1;i<Order;i++) 3959 FragmentSearch.BondsPerSPCount[i] = 0; 3960 FragmentSearch.BondsPerSPCount[0] = 1; 3961 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 3962 add(Binder, FragmentSearch.BondsPerSPList[1]); 3963 3964 // do a BFS search to fill the SP lists and label the found vertices 3965 // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into 3966 // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning 3967 // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth 3968 // (EdgeinSPLevel) of this tree ... 3969 // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence 3970 // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction. 3971 *out << endl; 3972 *out << Verbose(0) << "Starting BFS analysis ..." << endl; 3973 for (SP = 0; SP < (Order-1); SP++) { 3974 *out << Verbose(1) << "New SP level reached: " << SP << ", creating new SP list with " << FragmentSearch.BondsPerSPCount[SP] << " item(s)"; 3975 if (SP > 0) { 3976 *out << ", old level closed with " << FragmentSearch.BondsPerSPCount[SP-1] << " item(s)." << endl; 3977 FragmentSearch.BondsPerSPCount[SP] = 0; 3978 } else 3979 *out << "." << endl; 3980 3981 RemainingWalkers = FragmentSearch.BondsPerSPCount[SP]; 3982 CurrentEdge = FragmentSearch.BondsPerSPList[2*SP]; /// start of this SP level's list 3983 while (CurrentEdge->next != FragmentSearch.BondsPerSPList[2*SP+1]) { /// end of this SP level's list 3984 CurrentEdge = CurrentEdge->next; 3985 RemainingWalkers--; 3986 Walker = CurrentEdge->rightatom; // rightatom is always the one more distant 3987 Predecessor = CurrentEdge->leftatom; // ... and leftatom is predecessor 3988 AtomKeyNr = Walker->nr; 3989 *out << Verbose(0) << "Current Walker is: " << *Walker << " with nr " << Walker->nr << " and SP of " << SP << ", with " << RemainingWalkers << " remaining walkers on this level." << endl; 3990 // check for new sp level 3991 // go through all its bonds 3992 *out << Verbose(1) << "Going through all bonds of Walker." << endl; 3993 for (int i=0;i<NumberOfBondsPerAtom[AtomKeyNr];i++) { 3994 Binder = ListOfBondsPerAtom[AtomKeyNr][i]; 3995 OtherWalker = Binder->GetOtherAtom(Walker); 3996 if ((RestrictedKeySet.find(OtherWalker->nr) != RestrictedKeySet.end()) 3997 #ifdef ADDHYDROGEN 3998 && (OtherWalker->type->Z != 1) 3999 #endif 4000 ) { // skip hydrogens and restrict to fragment 4001 *out << Verbose(2) << "Current partner is " << *OtherWalker << " with nr " << OtherWalker->nr << " in bond " << *Binder << "." << endl; 4002 // set the label if not set (and push on root stack as well) 4003 if ((OtherWalker != Predecessor) && (OtherWalker->GetTrueFather()->nr > RootKeyNr)) { // only pass through those with label bigger than Root's 4004 FragmentSearch.ShortestPathList[OtherWalker->nr] = SP+1; 4005 *out << Verbose(3) << "Set Shortest Path to " << FragmentSearch.ShortestPathList[OtherWalker->nr] << "." << endl; 4006 // add the bond in between to the SP list 4007 Binder = new bond(Walker, OtherWalker); // create a new bond in such a manner, that bond::rightatom is always the one more distant 4008 add(Binder, FragmentSearch.BondsPerSPList[2*(SP+1)+1]); 4009 FragmentSearch.BondsPerSPCount[SP+1]++; 4010 *out << Verbose(3) << "Added its bond to SP list, having now " << FragmentSearch.BondsPerSPCount[SP+1] << " item(s)." << endl; 4011 } else { 4012 if (OtherWalker != Predecessor) 4013 *out << Verbose(3) << "Not passing on, as index of " << *OtherWalker << " " << OtherWalker->GetTrueFather()->nr << " is smaller than that of Root " << RootKeyNr << "." << endl; 4014 else 4015 *out << Verbose(3) << "This is my predecessor " << *Predecessor << "." << endl; 4016 } 4017 } else *out << Verbose(2) << "Is not in the restricted keyset or skipping hydrogen " << *OtherWalker << "." << endl; 4018 } 4019 } 4020 } 4021 4022 // outputting all list for debugging 4023 *out << Verbose(0) << "Printing all found lists." << endl; 4024 for(int i=1;i<Order;i++) { // skip the root edge in the printing 4025 Binder = FragmentSearch.BondsPerSPList[2*i]; 4026 *out << Verbose(1) << "Current SP level is " << i << "." << endl; 4027 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 4028 Binder = Binder->next; 4029 *out << Verbose(2) << *Binder << endl; 4030 } 4031 } 4032 4033 // creating fragments with the found edge sets (may be done in reverse order, faster) 4034 SP = -1; // the Root <-> Root edge must be subtracted! 4035 for(int i=Order;i--;) { // sum up all found edges 4036 Binder = FragmentSearch.BondsPerSPList[2*i]; 4037 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 4038 Binder = Binder->next; 4039 SP ++; 4040 } 4041 } 4042 *out << Verbose(0) << "Total number of edges is " << SP << "." << endl; 4043 if (SP >= (Order-1)) { 4044 // start with root (push on fragment stack) 4045 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl; 4046 FragmentSearch.FragmentSet->clear(); 4047 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl; 4048 // prepare the subset and call the generator 4049 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList"); 4050 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next; // on SP level 0 there's only the root bond 4051 4052 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order); 4053 4054 Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList"); 4055 } else { 4056 *out << Verbose(0) << "Not enough total number of edges to build " << Order << "-body fragments." << endl; 4057 } 4058 4059 // as FragmentSearch structure is used only once, we don't have to clean it anymore 4060 // remove root from stack 4061 *out << Verbose(0) << "Removing root again from stack." << endl; 4062 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4063 4064 // free'ing the bonds lists 4065 *out << Verbose(0) << "Free'ing all found lists. and resetting index lists" << endl; 4066 for(int i=Order;i--;) { 4067 *out << Verbose(1) << "Current SP level is " << i << ": "; 4068 Binder = FragmentSearch.BondsPerSPList[2*i]; 4069 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 4070 Binder = Binder->next; 4071 // *out << "Removing atom " << Binder->leftatom->nr << " and " << Binder->rightatom->nr << "." << endl; // make sure numbers are local 4072 FragmentSearch.ShortestPathList[Binder->leftatom->nr] = -1; 4073 FragmentSearch.ShortestPathList[Binder->rightatom->nr] = -1; 4074 } 4075 // delete added bonds 4076 cleanup(FragmentSearch.BondsPerSPList[2*i], FragmentSearch.BondsPerSPList[2*i+1]); 4077 // also start and end node 4078 *out << "cleaned." << endl; 4079 } 4080 4081 // return list 4082 *out << Verbose(0) << "End of PowerSetGenerator." << endl; 4083 return (FragmentSearch.FragmentCounter - Counter); 4084 4084 }; 4085 4085 … … 4092 4092 void molecule::ScanForPeriodicCorrection(ofstream *out) 4093 4093 { 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 unlink(Binder);// unlink bond4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 ColorList[Walker->nr] = black;// mark as explored4149 4150 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {// go through all binding partners4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4094 bond *Binder = NULL; 4095 bond *OtherBinder = NULL; 4096 atom *Walker = NULL; 4097 atom *OtherWalker = NULL; 4098 double *matrix = ReturnFullMatrixforSymmetric(cell_size); 4099 enum Shading *ColorList = NULL; 4100 double tmp; 4101 Vector Translationvector; 4102 //class StackClass<atom *> *CompStack = NULL; 4103 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount); 4104 bool flag = true; 4105 4106 *out << Verbose(2) << "Begin of ScanForPeriodicCorrection." << endl; 4107 4108 ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::ScanForPeriodicCorrection: *ColorList"); 4109 while (flag) { 4110 // remove bonds that are beyond bonddistance 4111 for(int i=NDIM;i--;) 4112 Translationvector.x[i] = 0.; 4113 // scan all bonds 4114 Binder = first; 4115 flag = false; 4116 while ((!flag) && (Binder->next != last)) { 4117 Binder = Binder->next; 4118 for (int i=NDIM;i--;) { 4119 tmp = fabs(Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]); 4120 //*out << Verbose(3) << "Checking " << i << "th distance of " << *Binder->leftatom << " to " << *Binder->rightatom << ": " << tmp << "." << endl; 4121 if (tmp > BondDistance) { 4122 OtherBinder = Binder->next; // note down binding partner for later re-insertion 4123 unlink(Binder); // unlink bond 4124 *out << Verbose(2) << "Correcting at bond " << *Binder << "." << endl; 4125 flag = true; 4126 break; 4127 } 4128 } 4129 } 4130 if (flag) { 4131 // create translation vector from their periodically modified distance 4132 for (int i=NDIM;i--;) { 4133 tmp = Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]; 4134 if (fabs(tmp) > BondDistance) 4135 Translationvector.x[i] = (tmp < 0) ? +1. : -1.; 4136 } 4137 Translationvector.MatrixMultiplication(matrix); 4138 //*out << Verbose(3) << "Translation vector is "; 4139 Translationvector.Output(out); 4140 *out << endl; 4141 // apply to all atoms of first component via BFS 4142 for (int i=AtomCount;i--;) 4143 ColorList[i] = white; 4144 AtomStack->Push(Binder->leftatom); 4145 while (!AtomStack->IsEmpty()) { 4146 Walker = AtomStack->PopFirst(); 4147 //*out << Verbose (3) << "Current Walker is: " << *Walker << "." << endl; 4148 ColorList[Walker->nr] = black; // mark as explored 4149 Walker->x.AddVector(&Translationvector); // translate 4150 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through all binding partners 4151 if (ListOfBondsPerAtom[Walker->nr][i] != Binder) { 4152 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 4153 if (ColorList[OtherWalker->nr] == white) { 4154 AtomStack->Push(OtherWalker); // push if yet unexplored 4155 } 4156 } 4157 } 4158 } 4159 // re-add bond 4160 link(Binder, OtherBinder); 4161 } else { 4162 *out << Verbose(3) << "No corrections for this fragment." << endl; 4163 } 4164 //delete(CompStack); 4165 } 4166 4167 // free allocated space from ReturnFullMatrixforSymmetric() 4168 delete(AtomStack); 4169 Free((void **)&ColorList, "molecule::ScanForPeriodicCorrection: *ColorList"); 4170 Free((void **)&matrix, "molecule::ScanForPeriodicCorrection: *matrix"); 4171 *out << Verbose(2) << "End of ScanForPeriodicCorrection." << endl; 4172 4172 }; 4173 4173 … … 4178 4178 double * molecule::ReturnFullMatrixforSymmetric(double *symm) 4179 4179 { 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4180 double *matrix = (double *) Malloc(sizeof(double)*NDIM*NDIM, "molecule::ReturnFullMatrixforSymmetric: *matrix"); 4181 matrix[0] = symm[0]; 4182 matrix[1] = symm[1]; 4183 matrix[2] = symm[2]; 4184 matrix[3] = symm[1]; 4185 matrix[4] = symm[3]; 4186 matrix[5] = symm[4]; 4187 matrix[6] = symm[2]; 4188 matrix[7] = symm[4]; 4189 matrix[8] = symm[5]; 4190 return matrix; 4191 4191 }; 4192 4192 4193 4193 bool KeyCompare::operator() (const KeySet SubgraphA, const KeySet SubgraphB) const 4194 4194 { 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 if ((*IteratorA) <(*IteratorB))4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4195 //cout << "my check is used." << endl; 4196 if (SubgraphA.size() < SubgraphB.size()) { 4197 return true; 4198 } else { 4199 if (SubgraphA.size() > SubgraphB.size()) { 4200 return false; 4201 } else { 4202 KeySet::iterator IteratorA = SubgraphA.begin(); 4203 KeySet::iterator IteratorB = SubgraphB.begin(); 4204 while ((IteratorA != SubgraphA.end()) && (IteratorB != SubgraphB.end())) { 4205 if ((*IteratorA) < (*IteratorB)) 4206 return true; 4207 else if ((*IteratorA) > (*IteratorB)) { 4208 return false; 4209 } // else, go on to next index 4210 IteratorA++; 4211 IteratorB++; 4212 } // end of while loop 4213 }// end of check in case of equal sizes 4214 } 4215 return false; // if we reach this point, they are equal 4216 4216 }; 4217 4217 4218 4218 //bool operator < (KeySet SubgraphA, KeySet SubgraphB) 4219 4219 //{ 4220 // 4220 // return KeyCompare(SubgraphA, SubgraphB); 4221 4221 //}; 4222 4222 … … 4230 4230 inline void InsertFragmentIntoGraph(ofstream *out, struct UniqueFragments *Fragment) 4231 4231 { 4232 4233 4234 testGraphInsert = Fragment->Leaflet->insert(GraphPair (*Fragment->FragmentSet,pair<int,double>(Fragment->FragmentCounter,Fragment->TEFactor)));// store fragment number and current factor4235 4236 4237 4238 4239 4240 ((*(testGraphInsert.first)).second).second += Fragment->TEFactor;// increase the "created" counter4241 4242 4232 GraphTestPair testGraphInsert; 4233 4234 testGraphInsert = Fragment->Leaflet->insert(GraphPair (*Fragment->FragmentSet,pair<int,double>(Fragment->FragmentCounter,Fragment->TEFactor))); // store fragment number and current factor 4235 if (testGraphInsert.second) { 4236 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " successfully inserted." << endl; 4237 Fragment->FragmentCounter++; 4238 } else { 4239 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl; 4240 ((*(testGraphInsert.first)).second).second += Fragment->TEFactor; // increase the "created" counter 4241 *out << Verbose(2) << "New factor is " << ((*(testGraphInsert.first)).second).second << "." << endl; 4242 } 4243 4243 }; 4244 4244 //void inline InsertIntoGraph(ofstream *out, KeyStack &stack, Graph &graph, int *counter, double factor) 4245 4245 //{ 4246 // 4247 // 4248 // 4249 // 4250 // 4246 // // copy stack contents to set and call overloaded function again 4247 // KeySet set; 4248 // for(KeyStack::iterator runner = stack.begin(); runner != stack.begin(); runner++) 4249 // set.insert((*runner)); 4250 // InsertIntoGraph(out, set, graph, counter, factor); 4251 4251 //}; 4252 4252 … … 4259 4259 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter) 4260 4260 { 4261 4262 4263 4264 testGraphInsert = graph1.insert(GraphPair ((*runner).first,pair<int,double>((*counter)++,((*runner).second).second)));// store fragment number and current factor4265 4266 4267 4268 4269 4270 4271 4272 4261 GraphTestPair testGraphInsert; 4262 4263 for(Graph::iterator runner = graph2.begin(); runner != graph2.end(); runner++) { 4264 testGraphInsert = graph1.insert(GraphPair ((*runner).first,pair<int,double>((*counter)++,((*runner).second).second))); // store fragment number and current factor 4265 if (testGraphInsert.second) { 4266 *out << Verbose(2) << "KeySet " << (*counter)-1 << " successfully inserted." << endl; 4267 } else { 4268 *out << Verbose(2) << "KeySet " << (*counter)-1 << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl; 4269 ((*(testGraphInsert.first)).second).second += (*runner).second.second; 4270 *out << Verbose(2) << "New factor is " << (*(testGraphInsert.first)).second.second << "." << endl; 4271 } 4272 } 4273 4273 }; 4274 4274 … … 4277 4277 * -# constructs a complete keyset of the molecule 4278 4278 * -# In a loop over all possible roots from the given rootstack 4279 * 4280 * 4281 * 4279 * -# increases order of root site 4280 * -# calls PowerSetGenerator with this order, the complete keyset and the rootkeynr 4281 * -# for all consecutive lower levels PowerSetGenerator is called with the suborder, the higher order keyset 4282 4282 as the restricted one and each site in the set as the root) 4283 * 4283 * -# these are merged into a fragment list of keysets 4284 4284 * -# All fragment lists (for all orders, i.e. from all destination fields) are merged into one list for return 4285 4285 * Important only is that we create all fragments, it is not important if we create them more than once … … 4293 4293 void molecule::FragmentBOSSANOVA(ofstream *out, Graph *&FragmentList, KeyStack &RootStack, int *MinimumRingSize) 4294 4294 { 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 RootNr = 0;// counts through the roots in RootStack4332 4333 4334 4335 4336 4337 4338 //*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;4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 FragmentSearch.BondsPerSPList[2*i] = new bond();// start node4350 FragmentSearch.BondsPerSPList[2*i+1] = new bond();// end node4351 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1];// intertwine these two4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 FragmentLowerOrdersList[RootNr][0] =new Graph;4368 4369 FragmentSearch.Leaflet = FragmentLowerOrdersList[RootNr][0];// set to insertion graph4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 // 4380 // 4381 // 4382 // 4383 // 4384 // 4385 // 4386 // 4387 // 4388 // 4389 // 4390 // 4391 // 4295 Graph ***FragmentLowerOrdersList = NULL; 4296 int NumLevels, NumMolecules, TotalNumMolecules = 0, *NumMoleculesOfOrder = NULL; 4297 int counter = 0, Order; 4298 int UpgradeCount = RootStack.size(); 4299 KeyStack FragmentRootStack; 4300 int RootKeyNr, RootNr; 4301 struct UniqueFragments FragmentSearch; 4302 4303 *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl; 4304 4305 // FragmentLowerOrdersList is a 2D-array of pointer to MoleculeListClass objects, one dimension represents the ANOVA expansion of a single order (i.e. 5) 4306 // with all needed lower orders that are subtracted, the other dimension is the BondOrder (i.e. from 1 to 5) 4307 NumMoleculesOfOrder = (int *) Malloc(sizeof(int)*UpgradeCount, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder"); 4308 FragmentLowerOrdersList = (Graph ***) Malloc(sizeof(Graph **)*UpgradeCount, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); 4309 4310 // initialise the fragments structure 4311 FragmentSearch.ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::PowerSetGenerator: *ShortestPathList"); 4312 FragmentSearch.FragmentCounter = 0; 4313 FragmentSearch.FragmentSet = new KeySet; 4314 FragmentSearch.Root = FindAtom(RootKeyNr); 4315 for (int i=AtomCount;i--;) { 4316 FragmentSearch.ShortestPathList[i] = -1; 4317 } 4318 4319 // Construct the complete KeySet which we need for topmost level only (but for all Roots) 4320 atom *Walker = start; 4321 KeySet CompleteMolecule; 4322 while (Walker->next != end) { 4323 Walker = Walker->next; 4324 CompleteMolecule.insert(Walker->GetTrueFather()->nr); 4325 } 4326 4327 // 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 4328 // 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), 4329 // hence we have overall four 2th order levels for splitting. This also allows for putting all into a single array (FragmentLowerOrdersList[]) 4330 // 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) 4331 RootNr = 0; // counts through the roots in RootStack 4332 while ((RootNr < UpgradeCount) && (!RootStack.empty())) { 4333 RootKeyNr = RootStack.front(); 4334 RootStack.pop_front(); 4335 Walker = FindAtom(RootKeyNr); 4336 // check cyclic lengths 4337 //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) { 4338 // *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; 4339 //} else 4340 { 4341 // increase adaptive order by one 4342 Walker->GetTrueFather()->AdaptiveOrder++; 4343 Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder; 4344 4345 // initialise Order-dependent entries of UniqueFragments structure 4346 FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList"); 4347 FragmentSearch.BondsPerSPCount = (int *) Malloc(sizeof(int)*Order, "molecule::PowerSetGenerator: *BondsPerSPCount"); 4348 for (int i=Order;i--;) { 4349 FragmentSearch.BondsPerSPList[2*i] = new bond(); // start node 4350 FragmentSearch.BondsPerSPList[2*i+1] = new bond(); // end node 4351 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1]; // intertwine these two 4352 FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i]; 4353 FragmentSearch.BondsPerSPCount[i] = 0; 4354 } 4355 4356 // allocate memory for all lower level orders in this 1D-array of ptrs 4357 NumLevels = 1 << (Order-1); // (int)pow(2,Order); 4358 FragmentLowerOrdersList[RootNr] = (Graph **) Malloc(sizeof(Graph *)*NumLevels, "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]"); 4359 for (int i=0;i<NumLevels;i++) 4360 FragmentLowerOrdersList[RootNr][i] = NULL; 4361 4362 // create top order where nothing is reduced 4363 *out << Verbose(0) << "==============================================================================================================" << endl; 4364 *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << " 4365 4366 // Create list of Graphs of current Bond Order (i.e. F_{ij}) 4367 FragmentLowerOrdersList[RootNr][0] = new Graph; 4368 FragmentSearch.TEFactor = 1.; 4369 FragmentSearch.Leaflet = FragmentLowerOrdersList[RootNr][0]; // set to insertion graph 4370 FragmentSearch.Root = Walker; 4371 NumMoleculesOfOrder[RootNr] = PowerSetGenerator(out, Walker->AdaptiveOrder, FragmentSearch, CompleteMolecule); 4372 *out << Verbose(1) << "Number of resulting KeySets is: " << NumMoleculesOfOrder[RootNr] << "." << endl; 4373 if (NumMoleculesOfOrder[RootNr] != 0) { 4374 NumMolecules = 0; 4375 4376 // we don't have to dive into suborders! These keysets are all already created on lower orders! 4377 // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed) 4378 4379 // if ((NumLevels >> 1) > 0) { 4380 // // create lower order fragments 4381 // *out << Verbose(0) << "Creating list of unique fragments of lower Bond Order terms to be subtracted." << endl; 4382 // Order = Walker->AdaptiveOrder; 4383 // 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) 4384 // // step down to next order at (virtual) boundary of powers of 2 in array 4385 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order)) 4386 // Order--; 4387 // *out << Verbose(0) << "Current Order is: " << Order << "." << endl; 4388 // for (int SubOrder=Order-1;SubOrder>0;SubOrder--) { 4389 // int dest = source + (1 << (Walker->AdaptiveOrder-(SubOrder+1))); 4390 // *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl; 4391 // *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl; 4392 4392 // 4393 // 4394 // 4395 // 4396 // 4397 // 4398 // 4399 // 4400 // 4401 // FragmentSearch.Leaflet = &TempFragmentList;// set to insertion graph4402 // 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 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4393 // // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules 4394 // //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl; 4395 // //NumMolecules = 0; 4396 // FragmentLowerOrdersList[RootNr][dest] = new Graph; 4397 // for(Graph::iterator runner = (*FragmentLowerOrdersList[RootNr][source]).begin();runner != (*FragmentLowerOrdersList[RootNr][source]).end(); runner++) { 4398 // for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 4399 // Graph TempFragmentList; 4400 // FragmentSearch.TEFactor = -(*runner).second.second; 4401 // FragmentSearch.Leaflet = &TempFragmentList; // set to insertion graph 4402 // FragmentSearch.Root = FindAtom(*sprinter); 4403 // NumMoleculesOfOrder[RootNr] += PowerSetGenerator(out, SubOrder, FragmentSearch, (*runner).first); 4404 // // insert new keysets FragmentList into FragmentLowerOrdersList[Walker->AdaptiveOrder-1][dest] 4405 // *out << Verbose(1) << "Merging resulting key sets with those present in destination " << dest << "." << endl; 4406 // InsertGraphIntoGraph(out, *FragmentLowerOrdersList[RootNr][dest], TempFragmentList, &NumMolecules); 4407 // } 4408 // } 4409 // *out << Verbose(1) << "Number of resulting molecules for SubOrder " << SubOrder << " is: " << NumMolecules << "." << endl; 4410 // } 4411 // } 4412 // } 4413 } else { 4414 Walker->GetTrueFather()->MaxOrder = true; 4415 // *out << Verbose(1) << "Hence, we don't dive into SubOrders ... " << endl; 4416 } 4417 // now, we have completely filled each cell of FragmentLowerOrdersList[] for the current Walker->AdaptiveOrder 4418 //NumMoleculesOfOrder[Walker->AdaptiveOrder-1] = NumMolecules; 4419 TotalNumMolecules += NumMoleculesOfOrder[RootNr]; 4420 // *out << Verbose(1) << "Number of resulting molecules for Order " << (int)Walker->GetTrueFather()->AdaptiveOrder << " is: " << NumMoleculesOfOrder[RootNr] << "." << endl; 4421 RootStack.push_back(RootKeyNr); // put back on stack 4422 RootNr++; 4423 4424 // free Order-dependent entries of UniqueFragments structure for next loop cycle 4425 Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount"); 4426 for (int i=Order;i--;) { 4427 delete(FragmentSearch.BondsPerSPList[2*i]); 4428 delete(FragmentSearch.BondsPerSPList[2*i+1]); 4429 } 4430 Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList"); 4431 } 4432 } 4433 *out << Verbose(0) << "==============================================================================================================" << endl; 4434 *out << Verbose(1) << "Total number of resulting molecules is: " << TotalNumMolecules << "." << endl; 4435 *out << Verbose(0) << "==============================================================================================================" << endl; 4436 4437 // cleanup FragmentSearch structure 4438 Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList"); 4439 delete(FragmentSearch.FragmentSet); 4440 4441 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein) 4442 // 5433222211111111 4443 // 43221111 4444 // 3211 4445 // 21 4446 // 1 4447 4448 // Subsequently, we combine all into a single list (FragmentList) 4449 4450 *out << Verbose(0) << "Combining the lists of all orders per order and finally into a single one." << endl; 4451 if (FragmentList == NULL) { 4452 FragmentList = new Graph; 4453 counter = 0; 4454 } else { 4455 counter = FragmentList->size(); 4456 } 4457 RootNr = 0; 4458 while (!RootStack.empty()) { 4459 RootKeyNr = RootStack.front(); 4460 RootStack.pop_front(); 4461 Walker = FindAtom(RootKeyNr); 4462 NumLevels = 1 << (Walker->AdaptiveOrder - 1); 4463 for(int i=0;i<NumLevels;i++) { 4464 if (FragmentLowerOrdersList[RootNr][i] != NULL) { 4465 InsertGraphIntoGraph(out, *FragmentList, (*FragmentLowerOrdersList[RootNr][i]), &counter); 4466 delete(FragmentLowerOrdersList[RootNr][i]); 4467 } 4468 } 4469 Free((void **)&FragmentLowerOrdersList[RootNr], "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]"); 4470 RootNr++; 4471 } 4472 Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); 4473 Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder"); 4474 4475 *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl; 4476 4476 }; 4477 4477 … … 4483 4483 inline int CompareDoubles (const void * a, const void * b) 4484 4484 { 4485 4486 4487 4488 4489 4490 4485 if (*(double *)a > *(double *)b) 4486 return -1; 4487 else if (*(double *)a < *(double *)b) 4488 return 1; 4489 else 4490 return 0; 4491 4491 }; 4492 4492 … … 4499 4499 int * molecule::IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold) 4500 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 //*out << Verbose(5) << "Element " <<flag << ": " << ElementsInMolecule[flag] << " <-> " << OtherMolecule->ElementsInMolecule[flag] << "." << endl;4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 *out << Verbose(5) << "Distances squared: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " <<threshold << endl;4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4501 int flag; 4502 double *Distances = NULL, *OtherDistances = NULL; 4503 Vector CenterOfGravity, OtherCenterOfGravity; 4504 size_t *PermMap = NULL, *OtherPermMap = NULL; 4505 int *PermutationMap = NULL; 4506 atom *Walker = NULL; 4507 bool result = true; // status of comparison 4508 4509 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 4510 /// first count both their atoms and elements and update lists thereby ... 4511 //*out << Verbose(0) << "Counting atoms, updating list" << endl; 4512 CountAtoms(out); 4513 OtherMolecule->CountAtoms(out); 4514 CountElements(); 4515 OtherMolecule->CountElements(); 4516 4517 /// ... and compare: 4518 /// -# AtomCount 4519 if (result) { 4520 if (AtomCount != OtherMolecule->AtomCount) { 4521 *out << Verbose(4) << "AtomCounts don't match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl; 4522 result = false; 4523 } else *out << Verbose(4) << "AtomCounts match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl; 4524 } 4525 /// -# ElementCount 4526 if (result) { 4527 if (ElementCount != OtherMolecule->ElementCount) { 4528 *out << Verbose(4) << "ElementCount don't match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl; 4529 result = false; 4530 } else *out << Verbose(4) << "ElementCount match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl; 4531 } 4532 /// -# ElementsInMolecule 4533 if (result) { 4534 for (flag=MAX_ELEMENTS;flag--;) { 4535 //*out << Verbose(5) << "Element " << flag << ": " << ElementsInMolecule[flag] << " <-> " << OtherMolecule->ElementsInMolecule[flag] << "." << endl; 4536 if (ElementsInMolecule[flag] != OtherMolecule->ElementsInMolecule[flag]) 4537 break; 4538 } 4539 if (flag < MAX_ELEMENTS) { 4540 *out << Verbose(4) << "ElementsInMolecule don't match." << endl; 4541 result = false; 4542 } else *out << Verbose(4) << "ElementsInMolecule match." << endl; 4543 } 4544 /// then determine and compare center of gravity for each molecule ... 4545 if (result) { 4546 *out << Verbose(5) << "Calculating Centers of Gravity" << endl; 4547 DetermineCenter(CenterOfGravity); 4548 OtherMolecule->DetermineCenter(OtherCenterOfGravity); 4549 *out << Verbose(5) << "Center of Gravity: "; 4550 CenterOfGravity.Output(out); 4551 *out << endl << Verbose(5) << "Other Center of Gravity: "; 4552 OtherCenterOfGravity.Output(out); 4553 *out << endl; 4554 if (CenterOfGravity.DistanceSquared(&OtherCenterOfGravity) > threshold*threshold) { 4555 *out << Verbose(4) << "Centers of gravity don't match." << endl; 4556 result = false; 4557 } 4558 } 4559 4560 /// ... then make a list with the euclidian distance to this center for each atom of both molecules 4561 if (result) { 4562 *out << Verbose(5) << "Calculating distances" << endl; 4563 Distances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: Distances"); 4564 OtherDistances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: OtherDistances"); 4565 Walker = start; 4566 while (Walker->next != end) { 4567 Walker = Walker->next; 4568 Distances[Walker->nr] = CenterOfGravity.DistanceSquared(&Walker->x); 4569 } 4570 Walker = OtherMolecule->start; 4571 while (Walker->next != OtherMolecule->end) { 4572 Walker = Walker->next; 4573 OtherDistances[Walker->nr] = OtherCenterOfGravity.DistanceSquared(&Walker->x); 4574 } 4575 4576 /// ... sort each list (using heapsort (o(N log N)) from GSL) 4577 *out << Verbose(5) << "Sorting distances" << endl; 4578 PermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermMap"); 4579 OtherPermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *OtherPermMap"); 4580 gsl_heapsort_index (PermMap, Distances, AtomCount, sizeof(double), CompareDoubles); 4581 gsl_heapsort_index (OtherPermMap, OtherDistances, AtomCount, sizeof(double), CompareDoubles); 4582 PermutationMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermutationMap"); 4583 *out << Verbose(5) << "Combining Permutation Maps" << endl; 4584 for(int i=AtomCount;i--;) 4585 PermutationMap[PermMap[i]] = (int) OtherPermMap[i]; 4586 4587 /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all 4588 *out << Verbose(4) << "Comparing distances" << endl; 4589 flag = 0; 4590 for (int i=0;i<AtomCount;i++) { 4591 *out << Verbose(5) << "Distances squared: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " << threshold << endl; 4592 if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) > threshold*threshold) 4593 flag = 1; 4594 } 4595 Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap"); 4596 Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap"); 4597 4598 /// free memory 4599 Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances"); 4600 Free((void **)&OtherDistances, "molecule::IsEqualToWithinThreshold: OtherDistances"); 4601 if (flag) { // if not equal 4602 Free((void **)&PermutationMap, "molecule::IsEqualToWithinThreshold: *PermutationMap"); 4603 result = false; 4604 } 4605 } 4606 /// return pointer to map if all distances were below \a threshold 4607 *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl; 4608 if (result) { 4609 *out << Verbose(3) << "Result: Equal." << endl; 4610 return PermutationMap; 4611 } else { 4612 *out << Verbose(3) << "Result: Not equal." << endl; 4613 return NULL; 4614 } 4615 4615 }; 4616 4616 … … 4624 4624 int * molecule::GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule) 4625 4625 { 4626 4627 4628 int *AtomicMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::GetAtomicMap: *AtomicMap");//Calloc4629 4630 4631 if (OtherMolecule == this) {// same molecule4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4626 atom *Walker = NULL, *OtherWalker = NULL; 4627 *out << Verbose(3) << "Begin of GetFatherAtomicMap." << endl; 4628 int *AtomicMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::GetAtomicMap: *AtomicMap"); //Calloc 4629 for (int i=AtomCount;i--;) 4630 AtomicMap[i] = -1; 4631 if (OtherMolecule == this) { // same molecule 4632 for (int i=AtomCount;i--;) // no need as -1 means already that there is trivial correspondence 4633 AtomicMap[i] = i; 4634 *out << Verbose(4) << "Map is trivial." << endl; 4635 } else { 4636 *out << Verbose(4) << "Map is "; 4637 Walker = start; 4638 while (Walker->next != end) { 4639 Walker = Walker->next; 4640 if (Walker->father == NULL) { 4641 AtomicMap[Walker->nr] = -2; 4642 } else { 4643 OtherWalker = OtherMolecule->start; 4644 while (OtherWalker->next != OtherMolecule->end) { 4645 OtherWalker = OtherWalker->next; 4646 //for (int i=0;i<AtomCount;i++) { // search atom 4647 //for (int j=0;j<OtherMolecule->AtomCount;j++) { 4648 //*out << Verbose(4) << "Comparing father " << Walker->father << " with the other one " << OtherWalker->father << "." << endl; 4649 if (Walker->father == OtherWalker) 4650 AtomicMap[Walker->nr] = OtherWalker->nr; 4651 } 4652 } 4653 *out << AtomicMap[Walker->nr] << "\t"; 4654 } 4655 *out << endl; 4656 } 4657 *out << Verbose(3) << "End of GetFatherAtomicMap." << endl; 4658 return AtomicMap; 4659 4659 }; 4660 4660 … … 4670 4670 bool molecule::OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output) 4671 4671 { 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 }; 4672 double temperature; 4673 atom *Walker = NULL; 4674 // test stream 4675 if (output == NULL) 4676 return false; 4677 else 4678 *output << "# Step Temperature [K] Temperature [a.u.]" << endl; 4679 for (int step=startstep;step < endstep; step++) { // loop over all time steps 4680 temperature = 0.; 4681 Walker = start; 4682 while (Walker->next != end) { 4683 Walker = Walker->next; 4684 for (int i=NDIM;i--;) 4685 temperature += Walker->type->mass * Trajectories[Walker].U.at(step).x[i]* Trajectories[Walker].U.at(step).x[i]; 4686 } 4687 *output << step << "\t" << temperature*AtomicEnergyToKelvin << "\t" << temperature << endl; 4688 } 4689 return true; 4690 }; -
src/molecules.hpp
r205ccd r042f82 79 79 struct KeyCompare 80 80 { 81 81 bool operator() (const KeySet SubgraphA, const KeySet SubgraphB) const; 82 82 }; 83 83 84 84 struct Trajectory 85 85 { 86 vector<Vector> R;//!< position vector87 vector<Vector> U;//!< velocity vector88 vector<Vector> F;//!< last force vector89 atom *ptr;//!< pointer to atom whose trajectory we contain90 }; 91 92 //bool operator < (KeySet SubgraphA, KeySet SubgraphB); 86 vector<Vector> R; //!< position vector 87 vector<Vector> U; //!< velocity vector 88 vector<Vector> F; //!< last force vector 89 atom *ptr; //!< pointer to atom whose trajectory we contain 90 }; 91 92 //bool operator < (KeySet SubgraphA, KeySet SubgraphB); //note: this declaration is important, otherwise normal < is used (producing wrong order) 93 93 inline void InsertFragmentIntoGraph(ofstream *out, struct UniqueFragments *Fragment); // Insert a KeySet into a Graph 94 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter); 94 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter); // Insert all KeySet's in a Graph into another Graph 95 95 int CompareDoubles (const void * a, const void * b); 96 96 … … 100 100 101 101 // some algebraic matrix stuff 102 #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]) 103 #define RDET2(a0,a1,a2,a3) ((a0)*(a3)-(a1)*(a2)) 102 #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 103 #define RDET2(a0,a1,a2,a3) ((a0)*(a3)-(a1)*(a2)) //!< hard-coded determinant of a 2x2 matrix 104 104 105 105 … … 107 107 */ 108 108 struct LSQ_params { 109 110 109 Vector **vectors; 110 int num; 111 111 }; 112 112 … … 116 116 */ 117 117 struct lsq_params { 118 119 120 118 gsl_vector *x; 119 const molecule *mol; 120 element *type; 121 121 }; 122 122 … … 125 125 */ 126 126 class atom { 127 128 Vector x;//!< coordinate array of atom, giving position within cell129 Vector v;//!< velocity array of atom130 element *type;//!< pointing to element131 132 atom *next;//!< next atom in molecule list133 atom *father;//!< In many-body bond order fragmentations points to originating atom134 135 char *Name;//!< unique name used during many-body bond-order fragmentation136 int FixedIon;//!< config variable that states whether forces act on the ion or not137 int *sort;//!< sort criteria138 int nr;//!< continuous, unique number139 int GraphNr;//!< unique number, given in DepthFirstSearchAnalysis()140 141 142 143 bool IsCyclic;//!< whether atom belong to as cycle or not, determined in DepthFirstSearchAnalysis()144 unsigned char AdaptiveOrder;//!< current present bond order at site (0 means "not set")145 bool MaxOrder;//!< whether this atom as a root in fragmentation still creates more fragments on higher orders or not146 147 148 149 150 151 152 153 154 155 127 public: 128 Vector x; //!< coordinate array of atom, giving position within cell 129 Vector v; //!< velocity array of atom 130 element *type; //!< pointing to element 131 atom *previous; //!< previous atom in molecule list 132 atom *next; //!< next atom in molecule list 133 atom *father; //!< In many-body bond order fragmentations points to originating atom 134 atom *Ancestor; //!< "Father" in Depth-First-Search 135 char *Name; //!< unique name used during many-body bond-order fragmentation 136 int FixedIon; //!< config variable that states whether forces act on the ion or not 137 int *sort; //!< sort criteria 138 int nr; //!< continuous, unique number 139 int GraphNr; //!< unique number, given in DepthFirstSearchAnalysis() 140 int *ComponentNr;//!< belongs to this nonseparable components, given in DepthFirstSearchAnalysis() (if more than one, then is SeparationVertex) 141 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. 142 bool SeparationVertex; //!< whether this atom separates off subsets of atoms or not, determined in DepthFirstSearchAnalysis() 143 bool IsCyclic; //!< whether atom belong to as cycle or not, determined in DepthFirstSearchAnalysis() 144 unsigned char AdaptiveOrder; //!< current present bond order at site (0 means "not set") 145 bool MaxOrder; //!< whether this atom as a root in fragmentation still creates more fragments on higher orders or not 146 147 atom(); 148 ~atom(); 149 150 bool Output(int ElementNo, int AtomNo, ofstream *out, const char *comment = NULL) const; 151 bool OutputXYZLine(ofstream *out) const; 152 atom *GetTrueFather(); 153 bool Compare(atom &ptr); 154 155 private: 156 156 }; 157 157 … … 164 164 */ 165 165 class bond { 166 167 atom *leftatom;//!< first bond partner168 atom *rightatom;//!< second bond partner169 170 bond *next;//!< next atom in molecule list171 int HydrogenBond;//!< Number of hydrogen atoms in the bond172 int BondDegree;//!< single, double, triple, ... bond173 int nr;//!< unique number in a molecule, updated by molecule::CreateAdjacencyList()174 bool Cyclic;//!< flag whether bond is part of a cycle or not, given in DepthFirstSearchAnalysis()175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 enum Shading Used;//!< marker in depth-first search, DepthFirstSearchAnalysis()166 public: 167 atom *leftatom; //!< first bond partner 168 atom *rightatom; //!< second bond partner 169 bond *previous; //!< previous atom in molecule list 170 bond *next; //!< next atom in molecule list 171 int HydrogenBond; //!< Number of hydrogen atoms in the bond 172 int BondDegree; //!< single, double, triple, ... bond 173 int nr; //!< unique number in a molecule, updated by molecule::CreateAdjacencyList() 174 bool Cyclic; //!< flag whether bond is part of a cycle or not, given in DepthFirstSearchAnalysis() 175 enum EdgeType Type;//!< whether this is a tree or back edge 176 177 atom * GetOtherAtom(atom *Atom) const; 178 bond * GetFirstBond(); 179 bond * GetLastBond(); 180 181 bool MarkUsed(enum Shading color); 182 enum Shading IsUsed(); 183 void ResetUsed(); 184 bool Contains(const atom *ptr); 185 bool Contains(const int nr); 186 187 bond(); 188 bond(atom *left, atom *right); 189 bond(atom *left, atom *right, int degree); 190 bond(atom *left, atom *right, int degree, int number); 191 ~bond(); 192 193 private: 194 enum Shading Used; //!< marker in depth-first search, DepthFirstSearchAnalysis() 195 195 }; 196 196 … … 203 203 */ 204 204 class molecule { 205 206 207 208 atom *start;//!< start of atom list209 atom *end;//!< end of atom list210 bond *first;//!< start of bond list211 bond *last;//!< end of bond list212 213 214 int MDSteps;//!< The number of MD steps in Trajectories215 int *NumberOfBondsPerAtom;//!< Number of Bonds each atom has216 int AtomCount;//!< number of atoms, brought up-to-date by CountAtoms()217 int BondCount;//!< number of atoms, brought up-to-date by CountBonds()218 int ElementCount;//!< how many unique elements are therein219 220 int NoNonHydrogen;//!< number of non-hydrogen atoms in molecule221 int NoNonBonds;//!< number of non-hydrogen bonds in molecule222 int NoCyclicBonds;//!< number of cyclic bonds in molecule, by DepthFirstSearchAnalysis()223 double BondDistance;//!< typical bond distance used in CreateAdjacencyList() and furtheron224 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 int last_atom;//!< number given to last atom205 public: 206 double cell_size[6];//!< cell size 207 periodentafel *elemente; //!< periodic table with each element 208 atom *start; //!< start of atom list 209 atom *end; //!< end of atom list 210 bond *first; //!< start of bond list 211 bond *last; //!< end of bond list 212 bond ***ListOfBondsPerAtom; //!< pointer list for each atom and each bond it has 213 map<atom *, struct Trajectory> Trajectories; //!< contains old trajectory points 214 int MDSteps; //!< The number of MD steps in Trajectories 215 int *NumberOfBondsPerAtom; //!< Number of Bonds each atom has 216 int AtomCount; //!< number of atoms, brought up-to-date by CountAtoms() 217 int BondCount; //!< number of atoms, brought up-to-date by CountBonds() 218 int ElementCount; //!< how many unique elements are therein 219 int ElementsInMolecule[MAX_ELEMENTS]; //!< list whether element (sorted by atomic number) is alread present or not 220 int NoNonHydrogen; //!< number of non-hydrogen atoms in molecule 221 int NoNonBonds; //!< number of non-hydrogen bonds in molecule 222 int NoCyclicBonds; //!< number of cyclic bonds in molecule, by DepthFirstSearchAnalysis() 223 double BondDistance; //!< typical bond distance used in CreateAdjacencyList() and furtheron 224 bool ActiveFlag; //!< in a MoleculeListClass used to discern active from inactive molecules 225 Vector Center; //!< Center of molecule in a global box 226 char name[MAXSTRINGSIZE]; //!< arbitrary name 227 int IndexNr; //!< index of molecule in a MoleculeListClass 228 229 molecule(periodentafel *teil); 230 ~molecule(); 231 232 /// remove atoms from molecule. 233 bool AddAtom(atom *pointer); 234 bool RemoveAtom(atom *pointer); 235 bool UnlinkAtom(atom *pointer); 236 bool CleanupMolecule(); 237 238 /// Add/remove atoms to/from molecule. 239 atom * AddCopyAtom(atom *pointer); 240 bool AddXYZFile(string filename); 241 bool AddHydrogenReplacementAtom(ofstream *out, bond *Bond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem); 242 bond * AddBond(atom *first, atom *second, int degree); 243 bool RemoveBond(bond *pointer); 244 bool RemoveBonds(atom *BondPartner); 245 246 /// Find atoms. 247 atom * FindAtom(int Nr) const; 248 atom * AskAtom(string text); 249 250 /// Count and change present atoms' coordination. 251 void CountAtoms(ofstream *out); 252 void CountElements(); 253 void CalculateOrbitals(class config &configuration); 254 bool CenterInBox(ofstream *out); 255 void CenterEdge(ofstream *out, Vector *max); 256 void CenterOrigin(ofstream *out, Vector *max); 257 void CenterGravity(ofstream *out, Vector *max); 258 void Translate(const Vector *x); 259 void TranslatePeriodically(const Vector *trans); 260 void Mirror(const Vector *x); 261 void Align(Vector *n); 262 void Scale(double **factor); 263 void DetermineCenter(Vector ¢er); 264 Vector * DetermineCenterOfGravity(ofstream *out); 265 Vector * DetermineCenterOfAll(ofstream *out); 266 void SetNameFromFilename(char *filename); 267 void SetBoxDimension(Vector *dim); 268 double * ReturnFullMatrixforSymmetric(double *cell_size); 269 void ScanForPeriodicCorrection(ofstream *out); 270 void PrincipalAxisSystem(ofstream *out, bool DoRotate); 271 double VolumeOfConvexEnvelope(ofstream *out, bool IsAngstroem); 272 Vector* FindEmbeddingHole(ofstream *out, molecule *srcmol); 273 274 bool VerletForceIntegration(char *file, double delta_t, bool IsAngstroem); 275 276 bool CheckBounds(const Vector *x) const; 277 void GetAlignvector(struct lsq_params * par) const; 278 279 /// Initialising routines in fragmentation 280 void CreateAdjacencyList2(ofstream *out, ifstream *output); 281 void CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem); 282 void CreateListOfBondsPerAtom(ofstream *out); 283 284 // Graph analysis 285 MoleculeLeafClass * DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack); 286 void CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> *BackEdgeStack, int *&MinimumRingSize); 287 bool PickLocalBackEdges(ofstream *out, atom **ListOfLocalAtoms, class StackClass<bond *> *&ReferenceStack, class StackClass<bond *> *&LocalStack); 288 bond * FindNextUnused(atom *vertex); 289 void SetNextComponentNumber(atom *vertex, int nr); 290 void InitComponentNumbers(); 291 void OutputComponentNumber(ofstream *out, atom *vertex); 292 void ResetAllBondsToUnused(); 293 void ResetAllAtomNumbers(); 294 int CountCyclicBonds(ofstream *out); 295 bool CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment); 296 string GetColor(enum Shading color); 297 298 molecule *CopyMolecule(); 299 300 /// Fragment molecule by two different approaches: 301 int FragmentMolecule(ofstream *out, int Order, config *configuration); 302 bool CheckOrderAtSite(ofstream *out, bool *AtomMask, Graph *GlobalKeySetList, int Order, int *MinimumRingSize, char *path = NULL); 303 bool StoreAdjacencyToFile(ofstream *out, char *path); 304 bool CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms); 305 bool ParseOrderAtSiteFromFile(ofstream *out, char *path); 306 bool StoreOrderAtSiteFile(ofstream *out, char *path); 307 bool ParseKeySetFile(ofstream *out, char *filename, Graph *&FragmentList); 308 bool StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path); 309 bool StoreForcesFile(ofstream *out, MoleculeListClass *BondFragments, char *path, int *SortIndex); 310 bool CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex); 311 bool ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet); 312 void BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem); 313 /// -# BOSSANOVA 314 void FragmentBOSSANOVA(ofstream *out, Graph *&FragmentList, KeyStack &RootStack, int *MinimumRingSize); 315 int PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet); 316 bool BuildInducedSubgraph(ofstream *out, const molecule *Father); 317 molecule * StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem); 318 void SPFragmentGenerator(ofstream *out, struct UniqueFragments *FragmentSearch, int RootDistance, bond **BondsSet, int SetDimension, int SubOrder); 319 int LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList); 320 int GuesstimateFragmentCount(ofstream *out, int order); 321 322 // Recognize doubly appearing molecules in a list of them 323 int * IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold); 324 int * GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule); 325 326 // Output routines. 327 bool Output(ofstream *out); 328 bool OutputTrajectories(ofstream *out); 329 void OutputListOfBonds(ofstream *out) const; 330 bool OutputXYZ(ofstream *out) const; 331 bool OutputTrajectoriesXYZ(ofstream *out); 332 bool Checkout(ofstream *out) const; 333 bool OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output); 334 335 private: 336 int last_atom; //!< number given to last atom 337 337 }; 338 338 … … 340 340 */ 341 341 class MoleculeListClass { 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 342 public: 343 MoleculeList ListOfMolecules; //!< List of the contained molecules 344 int MaxIndex; 345 346 MoleculeListClass(); 347 ~MoleculeListClass(); 348 349 bool AddHydrogenCorrection(ofstream *out, char *path); 350 bool StoreForcesFile(ofstream *out, char *path, int *SortIndex); 351 bool insert(molecule *mol); 352 molecule * ReturnIndex(int index); 353 bool OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex); 354 int NumberOfActiveMolecules(); 355 void Enumerate(ofstream *out); 356 void Output(ofstream *out); 357 358 // merging of molecules 359 359 bool SimpleMerge(molecule *mol, molecule *srcmol); 360 360 bool SimpleAdd(molecule *mol, molecule *srcmol); … … 364 364 bool EmbedMerge(molecule *mol, molecule *srcmol); 365 365 366 366 private: 367 367 }; 368 368 … … 372 372 */ 373 373 class MoleculeLeafClass { 374 375 molecule *Leaf;//!< molecule of this leaf376 //MoleculeLeafClass *UpLeaf;//!< Leaf one level up377 //MoleculeLeafClass *DownLeaf;//!< First leaf one level down378 MoleculeLeafClass *previous;//!< Previous leaf on this level379 MoleculeLeafClass *next;//!< Next leaf on this level380 381 382 383 384 385 386 387 388 389 390 391 374 public: 375 molecule *Leaf; //!< molecule of this leaf 376 //MoleculeLeafClass *UpLeaf; //!< Leaf one level up 377 //MoleculeLeafClass *DownLeaf; //!< First leaf one level down 378 MoleculeLeafClass *previous; //!< Previous leaf on this level 379 MoleculeLeafClass *next; //!< Next leaf on this level 380 381 //MoleculeLeafClass(MoleculeLeafClass *Up, MoleculeLeafClass *Previous); 382 MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf); 383 ~MoleculeLeafClass(); 384 385 bool AddLeaf(molecule *ptr, MoleculeLeafClass *Previous); 386 bool FillBondStructureFromReference(ofstream *out, molecule *reference, int &FragmentCounter, atom ***&ListOfLocalAtoms, bool FreeList = false); 387 bool FillRootStackForSubgraphs(ofstream *out, KeyStack *&RootStack, bool *AtomMask, int &FragmentCounter); 388 bool AssignKeySetsToFragment(ofstream *out, molecule *reference, Graph *KeySetList, atom ***&ListOfLocalAtoms, Graph **&FragmentList, int &FragmentCounter, bool FreeList = false); 389 bool FillListOfLocalAtoms(ofstream *out, atom ***&ListOfLocalAtoms, const int FragmentCounter, const int GlobalAtomCount, bool &FreeList); 390 void TranslateIndicesToGlobalIDs(ofstream *out, Graph **FragmentList, int &FragmentCounter, int &TotalNumberOfKeySets, Graph &TotalGraph); 391 int Count() const; 392 392 }; 393 393 … … 412 412 */ 413 413 class config { 414 415 416 417 418 419 420 421 422 423 424 425 426 427 414 public: 415 int PsiType; 416 int MaxPsiDouble; 417 int PsiMaxNoUp; 418 int PsiMaxNoDown; 419 int MaxMinStopStep; 420 int InitMaxMinStopStep; 421 int ProcPEGamma; 422 int ProcPEPsi; 423 char *configpath; 424 char *configname; 425 bool FastParsing; 426 double Deltat; 427 string basis; 428 428 429 429 char *databasepath; 430 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 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 431 private: 432 char *mainname; 433 char *defaultpath; 434 char *pseudopotpath; 435 436 int DoOutVis; 437 int DoOutMes; 438 int DoOutNICS; 439 int DoOutOrbitals; 440 int DoOutCurrent; 441 int DoFullCurrent; 442 int DoPerturbation; 443 int DoWannier; 444 int CommonWannier; 445 double SawtoothStart; 446 int VectorPlane; 447 double VectorCut; 448 int UseAddGramSch; 449 int Seed; 450 451 int MaxOuterStep; 452 int OutVisStep; 453 int OutSrcStep; 454 double TargetTemp; 455 int ScaleTempStep; 456 int MaxPsiStep; 457 double EpsWannier; 458 459 int MaxMinStep; 460 double RelEpsTotalEnergy; 461 double RelEpsKineticEnergy; 462 int MaxMinGapStopStep; 463 int MaxInitMinStep; 464 double InitRelEpsTotalEnergy; 465 double InitRelEpsKineticEnergy; 466 int InitMaxMinGapStopStep; 467 468 //double BoxLength[NDIM*NDIM]; 469 470 double ECut; 471 int MaxLevel; 472 int RiemannTensor; 473 int LevRFactor; 474 int RiemannLevel; 475 int Lev0Factor; 476 int RTActualUse; 477 int AddPsis; 478 479 double RCut; 480 int StructOpt; 481 int IsAngstroem; 482 int RelativeCoord; 483 int MaxTypes; 484 485 486 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); 487 int ParseForParameter(int verbose, struct ConfigFileBuffer *FileBuffer, const char *name, int sequential, int const xth, int const yth, int type, void *value, int repetition, int critical); 488 489 public: 490 config(); 491 ~config(); 492 493 int TestSyntax(char *filename, periodentafel *periode, molecule *mol); 494 void Load(char *filename, periodentafel *periode, molecule *mol); 495 void LoadOld(char *filename, periodentafel *periode, molecule *mol); 496 void RetrieveConfigPathAndName(string filename); 497 bool Save(const char *filename, periodentafel *periode, molecule *mol) const; 498 bool SaveMPQC(const char *filename, molecule *mol) const; 499 void Edit(); 500 bool GetIsAngstroem() const; 501 char *GetDefaultPath() const; 502 void SetDefaultPath(const char *path); 503 503 }; 504 504 -
src/parser.cpp
r205ccd r042f82 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(const char *name, const 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(const 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(const char *name, const 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(const 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(const char *name, const 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
r205ccd r042f82 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(const char *name, const char *prefix, string suffix, int skiplines, int skipcolumns); 55 bool AllocateMatrix(const 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(const char *name, const 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(const char *name); 82 bool SumSubForces(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign); 83 bool ParseFragmentMatrix(const char *name, const 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
r205ccd r042f82 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(const 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(const 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(const char *path) const 304 304 { 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 }; 305 bool result = true; 306 ofstream f; 307 char filename[MAXSTRINGSIZE]; 308 309 strncpy(filename, path, MAXSTRINGSIZE); 310 strncat(filename, "/", MAXSTRINGSIZE-strlen(filename)); 311 strncat(filename, STANDARDELEMENTSDB, MAXSTRINGSIZE-strlen(filename)); 312 f.open(filename); 313 if (f != NULL) { 314 f << header1 << endl; 315 f << header2 << endl; 316 element *walker = periodentafel::start; 317 while (walker->next != periodentafel::end) { 318 walker = walker->next; 319 result = result && walker->Output(&f); 320 } 321 f.close(); 322 } else 323 result = false; 324 return result; 325 }; -
src/periodentafel.hpp
r205ccd r042f82 21 21 */ 22 22 class element { 23 24 double mass;//!< mass in g/mol25 double CovalentRadius;//!< covalent radius26 double VanDerWaalsRadius;//!< can-der-Waals radius27 int Z;//!< atomic number28 char name[64];//!< atom name, i.e. "Hydrogren"29 30 char period[8];//!< period: n quantum number31 char group[8];//!< group: l quantum number32 char block[8];//!< block: l quantum number33 element *previous;//!< previous item in list34 element *next;//!< next element in list35 int *sort;//!< sorc criteria36 int No;//!< number of element set on periodentafel::Output()37 double Valence;//!< number of valence electrons for this element38 int NoValenceOrbitals;//!< number of valence orbitals, used for determining bond degree in molecule::CreateConnectmatrix()39 double HBondDistance[NDIM]; //!< distance in Angstrom of this element to hydrogen(for single, double and triple bonds)40 double HBondAngle[NDIM];//!< typical angle for one, two, three bonded hydrogen (in degrees)23 public: 24 double mass; //!< mass in g/mol 25 double CovalentRadius; //!< covalent radius 26 double VanDerWaalsRadius; //!< can-der-Waals radius 27 int Z; //!< atomic number 28 char name[64]; //!< atom name, i.e. "Hydrogren" 29 char symbol[3]; //!< short form of the atom, i.e. "H" 30 char period[8]; //!< period: n quantum number 31 char group[8]; //!< group: l quantum number 32 char block[8]; //!< block: l quantum number 33 element *previous; //!< previous item in list 34 element *next; //!< next element in list 35 int *sort; //!< sorc criteria 36 int No; //!< number of element set on periodentafel::Output() 37 double Valence; //!< number of valence electrons for this element 38 int NoValenceOrbitals; //!< number of valence orbitals, used for determining bond degree in molecule::CreateConnectmatrix() 39 double HBondDistance[NDIM]; //!< distance in Angstrom of this element to hydrogen (for single, double and triple bonds) 40 double HBondAngle[NDIM]; //!< typical angle for one, two, three bonded hydrogen (in degrees) 41 41 42 43 42 element(); 43 ~element(); 44 44 45 46 47 45 //> print element entries to screen 46 bool Output(ofstream *out) const; 47 bool Checkout(ofstream *out, const int No, const int NoOfAtoms) const; 48 48 49 49 private: 50 50 }; 51 51 … … 53 53 */ 54 54 class periodentafel { 55 56 57 element *end;//!< end of element list58 59 55 public: 56 element *start; //!< start of element list 57 element *end; //!< end of element list 58 char header1[MAXSTRINGSIZE]; //!< store first header line 59 char header2[MAXSTRINGSIZE]; //!< store second header line 60 60 61 62 61 periodentafel(); 62 ~periodentafel(); 63 63 64 65 66 67 68 69 70 71 72 73 64 bool AddElement(element *pointer); 65 bool RemoveElement(element *pointer); 66 bool CleanupPeriodtable(); 67 element * FindElement(int Z); 68 element * FindElement(const char *shorthand) const; 69 element * AskElement(); 70 bool Output(ofstream *output) const; 71 bool Checkout(ofstream *output, const int *checkliste) const; 72 bool LoadPeriodentafel(const char *path); 73 bool StorePeriodentafel(const char *path) const; 74 74 75 75 private: 76 76 }; 77 77 -
src/stackclass.hpp
r205ccd r042f82 10 10 */ 11 11 template <typename T> class StackClass { 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 T *StackList;//!< the list containing the atom pointers29 int EntryCount;//!< number of entries in the stack30 int CurrentLastEntry;//!< Current last entry (newest item on stack)31 int CurrentFirstEntry;//!< Current first entry (oldest item on stack)32 int NextFreeField;//!< Current index of next free field12 public: 13 StackClass<T>(int dimension); 14 ~StackClass<T>(); 15 16 bool Push(T object); 17 T PopFirst(); 18 T PopLast(); 19 bool RemoveItem(T ptr); 20 void ClearStack(); 21 bool IsEmpty(); 22 bool IsFull(); 23 int ItemCount(); 24 void Output(ofstream *out) const; 25 void TestImplementation(ofstream *out, T test); 26 27 private: 28 T *StackList; //!< the list containing the atom pointers 29 int EntryCount; //!< number of entries in the stack 30 int CurrentLastEntry; //!< Current last entry (newest item on stack) 31 int CurrentFirstEntry; //!< Current first entry (oldest item on stack) 32 int NextFreeField; //!< Current index of next free field 33 33 }; 34 34 … … 37 37 template <typename T> StackClass<T>::StackClass(int dimension) 38 38 { 39 40 41 42 43 39 CurrentLastEntry = 0; 40 CurrentFirstEntry = 0; 41 NextFreeField = 0; 42 EntryCount = dimension; 43 StackList = (T *) Malloc(sizeof(T)*EntryCount, "StackClass::StackClass: **StackList"); 44 44 }; 45 45 … … 48 48 template <typename T> StackClass<T>::~StackClass() 49 49 { 50 50 Free((void **)&StackList, "StackClass::StackClass: **StackList"); 51 51 }; 52 52 … … 57 57 template <typename T> bool StackClass<T>::Push(T object) 58 58 { 59 if (!IsFull()) {// check whether free field is really not occupied60 61 62 63 64 65 66 67 59 if (!IsFull()) { // check whether free field is really not occupied 60 StackList[NextFreeField] = object; 61 CurrentLastEntry = NextFreeField; 62 NextFreeField = (NextFreeField + 1) % EntryCount; // step on to next free field 63 return true; 64 } else { 65 cerr << "ERROR: Stack is full, " << "Stack: CurrentLastEntry " << CurrentLastEntry<< "\tCurrentFirstEntry " << CurrentFirstEntry << "\tNextFreeField " << NextFreeField << "\tEntryCount " << EntryCount << "!" << endl; 66 return false; 67 } 68 68 }; 69 69 … … 74 74 template <typename T> T StackClass<T>::PopFirst() 75 75 { 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 76 T Walker = NULL; 77 if (!IsEmpty()) { 78 Walker = StackList[CurrentFirstEntry]; 79 if (Walker == NULL) 80 cerr << "ERROR: Stack's field is empty!" << endl; 81 StackList[CurrentFirstEntry] = NULL; 82 if (CurrentFirstEntry != CurrentLastEntry) { // hasn't last item been popped as well? 83 CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1) 84 } else { 85 CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1) 86 CurrentLastEntry = CurrentFirstEntry; 87 } 88 } else 89 cerr << "ERROR: Stack is empty!" << endl; 90 return Walker; 91 91 }; 92 92 … … 97 97 template <typename T> T StackClass<T>::PopLast() 98 98 { 99 100 101 102 103 104 105 106 if (CurrentLastEntry != CurrentFirstEntry)// has there been more than one item on stack107 108 109 110 111 99 T Walker = NULL; 100 if (!IsEmpty()) { 101 Walker = StackList[CurrentLastEntry]; 102 StackList[CurrentLastEntry] = NULL; 103 if (Walker == NULL) 104 cerr << "ERROR: Stack's field is empty!" << endl; 105 NextFreeField = CurrentLastEntry; 106 if (CurrentLastEntry != CurrentFirstEntry) // has there been more than one item on stack 107 CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount; // step back from current free field to last (modulo does not work in -1, thus go EntryCount-1 instead) 108 } else { 109 cerr << "ERROR: Stack is empty!" << endl; 110 } 111 return Walker; 112 112 }; 113 113 … … 120 120 template <typename T> bool StackClass<T>::RemoveItem(T ptr) 121 121 { 122 123 124 125 126 127 if (StackList[i] == ptr) {// if item found, remove128 129 130 131 132 if ((found) && (StackList[i] != NULL)) {// means we have to shift (and not the removed item)133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 if (CurrentLastEntry != CurrentFirstEntry)// has there been more than one item on stack148 149 150 122 bool found = false; 123 cout << Verbose(5) << "First " << CurrentFirstEntry<< "\tLast " << CurrentLastEntry<< "\tNext " << NextFreeField<< "\tCount " << EntryCount<< "." << endl; 124 int i=CurrentFirstEntry; 125 if (!IsEmpty()) 126 do { 127 if (StackList[i] == ptr) { // if item found, remove 128 cout << Verbose(5) << "Item " << *ptr << " was number " << i << " on stack, removing it." << endl; 129 found = true; 130 StackList[i] = NULL; 131 } 132 if ((found) && (StackList[i] != NULL)) { // means we have to shift (and not the removed item) 133 if (i == 0) { // we are down to first item in stack, have to put onto last item 134 cout << Verbose(5) << "Shifting item 0 to place " << EntryCount-1 << "." << endl; 135 StackList[EntryCount-1] = StackList[0]; 136 } else { 137 cout << Verbose(5) << "Shifting item " << i << " to place " << i-1 << "." << endl; 138 StackList[i-1] = StackList[i]; 139 } 140 } 141 i=((i + 1) % EntryCount); // step on 142 } while (i!=NextFreeField); 143 else 144 cerr << "ERROR: Stack is already empty!" << endl; 145 if (found) { 146 NextFreeField = CurrentLastEntry; 147 if (CurrentLastEntry != CurrentFirstEntry) // has there been more than one item on stack 148 CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount; 149 } 150 return found; 151 151 }; 152 152 … … 158 158 template <typename T> void StackClass<T>::TestImplementation(ofstream *out, T test) 159 159 { 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 *out << "Removing first element..." << endl;180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 160 T Walker = test; 161 *out << Verbose(1) << "Testing the snake stack..." << endl; 162 for (int i=0;i<EntryCount;i++) { 163 *out << Verbose(2) << "Filling " << i << "th element of stack." << endl; 164 Push(Walker); 165 Walker=Walker->next; 166 } 167 *out << endl; 168 Output(out); 169 if (IsFull()) 170 *out << "Stack is full as supposed to be!" << endl; 171 else 172 *out << "ERROR: Stack is not as full as supposed to be!" << endl; 173 //if (StackList[(EntryCount+1)/2] != NULL) { 174 *out << "Removing element in the middle ..." << endl; 175 RemoveItem(StackList[(EntryCount+1)/2]); 176 Output(out); 177 //} 178 //if (StackList[CurrentFirstEntry] != NULL) { 179 *out << "Removing first element ..." << endl; 180 RemoveItem(StackList[CurrentFirstEntry]); 181 Output(out); 182 //} 183 //if (StackList[CurrentLastEntry] != NULL) { 184 *out << "Removing last element ..." << endl; 185 RemoveItem(StackList[CurrentLastEntry]); 186 Output(out); 187 //} 188 *out << "Clearing stack ... " << endl; 189 ClearStack(); 190 Output(out); 191 if (IsEmpty()) 192 *out << "Stack is empty as supposed to be!" << endl; 193 else 194 *out << "ERROR: Stack is not as empty as supposed to be!" << endl; 195 *out << "done." << endl; 196 196 }; 197 197 … … 201 201 template <typename T> void StackClass<T>::Output(ofstream *out) const 202 202 { 203 204 205 206 207 208 if(i == CurrentLastEntry)209 210 if (i ==NextFreeField)211 212 213 214 203 *out << "Contents of Stack: "; 204 for(int i=0;i<EntryCount;i++) { 205 *out << "\t"; 206 if (i == CurrentFirstEntry) 207 *out << " 1"; 208 if (i == CurrentLastEntry) 209 *out << " "<< EntryCount; 210 if (i == NextFreeField) 211 *out << " F"; 212 *out << ": " << StackList[i]; 213 } 214 *out << endl; 215 215 }; 216 216 … … 222 222 template <typename T> bool StackClass<T>::IsEmpty() 223 223 { 224 224 return((NextFreeField == CurrentFirstEntry) && (CurrentLastEntry == CurrentFirstEntry)); 225 225 }; 226 226 … … 232 232 template <typename T> bool StackClass<T>::IsFull() 233 233 { 234 234 return((NextFreeField == CurrentFirstEntry) && (CurrentLastEntry != CurrentFirstEntry)); 235 235 }; 236 236 … … 242 242 template <typename T> int StackClass<T>::ItemCount() 243 243 { 244 245 244 //cout << "Stack: CurrentLastEntry " << CurrentLastEntry<< "\tCurrentFirstEntry " << CurrentFirstEntry << "\tEntryCount " << EntryCount << "." << endl; 245 return((NextFreeField + (EntryCount - CurrentFirstEntry)) % EntryCount); 246 246 }; 247 247 … … 251 251 template <typename T> void StackClass<T>::ClearStack() 252 252 { 253 254 255 256 257 253 for(int i=EntryCount; i--;) 254 StackList[i] = NULL; 255 CurrentFirstEntry = 0; 256 CurrentLastEntry = 0; 257 NextFreeField = 0; 258 258 }; 259 259 -
src/vector.cpp
r205ccd r042f82 28 28 double Vector::DistanceSquared(const Vector *y) const 29 29 { 30 31 32 33 30 double res = 0.; 31 for (int i=NDIM;i--;) 32 res += (x[i]-y->x[i])*(x[i]-y->x[i]); 33 return (res); 34 34 }; 35 35 … … 40 40 double Vector::Distance(const Vector *y) const 41 41 { 42 43 44 45 42 double res = 0.; 43 for (int i=NDIM;i--;) 44 res += (x[i]-y->x[i])*(x[i]-y->x[i]); 45 return (sqrt(res)); 46 46 }; 47 47 … … 53 53 double Vector::PeriodicDistance(const Vector *y, const double *cell_size) const 54 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 55 double res = Distance(y), tmp, matrix[NDIM*NDIM]; 56 Vector Shiftedy, TranslationVector; 57 int N[NDIM]; 58 matrix[0] = cell_size[0]; 59 matrix[1] = cell_size[1]; 60 matrix[2] = cell_size[3]; 61 matrix[3] = cell_size[1]; 62 matrix[4] = cell_size[2]; 63 matrix[5] = cell_size[4]; 64 matrix[6] = cell_size[3]; 65 matrix[7] = cell_size[4]; 66 matrix[8] = cell_size[5]; 67 // in order to check the periodic distance, translate one of the vectors into each of the 27 neighbouring cells 68 for (N[0]=-1;N[0]<=1;N[0]++) 69 for (N[1]=-1;N[1]<=1;N[1]++) 70 for (N[2]=-1;N[2]<=1;N[2]++) { 71 // create the translation vector 72 TranslationVector.Zero(); 73 for (int i=NDIM;i--;) 74 TranslationVector.x[i] = (double)N[i]; 75 TranslationVector.MatrixMultiplication(matrix); 76 // add onto the original vector to compare with 77 Shiftedy.CopyVector(y); 78 Shiftedy.AddVector(&TranslationVector); 79 // get distance and compare with minimum so far 80 tmp = Distance(&Shiftedy); 81 if (tmp < res) res = tmp; 82 } 83 return (res); 84 84 }; 85 85 … … 91 91 double Vector::PeriodicDistanceSquared(const Vector *y, const double *cell_size) const 92 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 93 double res = DistanceSquared(y), tmp, matrix[NDIM*NDIM]; 94 Vector Shiftedy, TranslationVector; 95 int N[NDIM]; 96 matrix[0] = cell_size[0]; 97 matrix[1] = cell_size[1]; 98 matrix[2] = cell_size[3]; 99 matrix[3] = cell_size[1]; 100 matrix[4] = cell_size[2]; 101 matrix[5] = cell_size[4]; 102 matrix[6] = cell_size[3]; 103 matrix[7] = cell_size[4]; 104 matrix[8] = cell_size[5]; 105 // in order to check the periodic distance, translate one of the vectors into each of the 27 neighbouring cells 106 for (N[0]=-1;N[0]<=1;N[0]++) 107 for (N[1]=-1;N[1]<=1;N[1]++) 108 for (N[2]=-1;N[2]<=1;N[2]++) { 109 // create the translation vector 110 TranslationVector.Zero(); 111 for (int i=NDIM;i--;) 112 TranslationVector.x[i] = (double)N[i]; 113 TranslationVector.MatrixMultiplication(matrix); 114 // add onto the original vector to compare with 115 Shiftedy.CopyVector(y); 116 Shiftedy.AddVector(&TranslationVector); 117 // get distance and compare with minimum so far 118 tmp = DistanceSquared(&Shiftedy); 119 if (tmp < res) res = tmp; 120 } 121 return (res); 122 122 }; 123 123 … … 128 128 void Vector::KeepPeriodic(ofstream *out, double *matrix) 129 129 { 130 // 131 // 132 133 134 // 135 // 136 // 137 // 138 139 140 141 if (TestVector.x[i] < 0) {// get every coefficient into the interval [0,1)142 143 144 145 146 147 148 149 // 150 // 151 // 152 // 130 // int N[NDIM]; 131 // bool flag = false; 132 //vector Shifted, TranslationVector; 133 Vector TestVector; 134 // *out << Verbose(1) << "Begin of KeepPeriodic." << endl; 135 // *out << Verbose(2) << "Vector is: "; 136 // Output(out); 137 // *out << endl; 138 TestVector.CopyVector(this); 139 TestVector.InverseMatrixMultiplication(matrix); 140 for(int i=NDIM;i--;) { // correct periodically 141 if (TestVector.x[i] < 0) { // get every coefficient into the interval [0,1) 142 TestVector.x[i] += ceil(TestVector.x[i]); 143 } else { 144 TestVector.x[i] -= floor(TestVector.x[i]); 145 } 146 } 147 TestVector.MatrixMultiplication(matrix); 148 CopyVector(&TestVector); 149 // *out << Verbose(2) << "New corrected vector is: "; 150 // Output(out); 151 // *out << endl; 152 // *out << Verbose(1) << "End of KeepPeriodic." << endl; 153 153 }; 154 154 … … 159 159 double Vector::ScalarProduct(const Vector *y) const 160 160 { 161 162 163 164 161 double res = 0.; 162 for (int i=NDIM;i--;) 163 res += x[i]*y->x[i]; 164 return (res); 165 165 }; 166 166 167 167 168 168 /** Calculates VectorProduct between this and another vector. 169 * 170 * 171 * 172 * 169 * -# returns the Product in place of vector from which it was initiated 170 * -# ATTENTION: Only three dim. 171 * \param *y array to vector with which to calculate crossproduct 172 * \return \f$ x \times y \f& 173 173 */ 174 174 void Vector::VectorProduct(const Vector *y) 175 175 { 176 177 178 179 180 176 Vector tmp; 177 tmp.x[0] = x[1]* (y->x[2]) - x[2]* (y->x[1]); 178 tmp.x[1] = x[2]* (y->x[0]) - x[0]* (y->x[2]); 179 tmp.x[2] = x[0]* (y->x[1]) - x[1]* (y->x[0]); 180 this->CopyVector(&tmp); 181 181 182 182 }; … … 189 189 void Vector::ProjectOntoPlane(const Vector *y) 190 190 { 191 192 193 194 195 191 Vector tmp; 192 tmp.CopyVector(y); 193 tmp.Normalize(); 194 tmp.Scale(ScalarProduct(&tmp)); 195 this->SubtractVector(&tmp); 196 196 }; 197 197 … … 202 202 double Vector::Projection(const Vector *y) const 203 203 { 204 204 return (ScalarProduct(y)); 205 205 }; 206 206 … … 210 210 double Vector::Norm() const 211 211 { 212 213 214 215 212 double res = 0.; 213 for (int i=NDIM;i--;) 214 res += this->x[i]*this->x[i]; 215 return (sqrt(res)); 216 216 }; 217 217 … … 220 220 void Vector::Normalize() 221 221 { 222 223 224 225 226 227 222 double res = 0.; 223 for (int i=NDIM;i--;) 224 res += this->x[i]*this->x[i]; 225 if (fabs(res) > MYEPSILON) 226 res = 1./sqrt(res); 227 Scale(&res); 228 228 }; 229 229 … … 232 232 void Vector::Zero() 233 233 { 234 235 234 for (int i=NDIM;i--;) 235 this->x[i] = 0.; 236 236 }; 237 237 … … 240 240 void Vector::One(double one) 241 241 { 242 243 242 for (int i=NDIM;i--;) 243 this->x[i] = one; 244 244 }; 245 245 … … 248 248 void Vector::Init(double x1, double x2, double x3) 249 249 { 250 251 252 250 x[0] = x1; 251 x[1] = x2; 252 x[2] = x3; 253 253 }; 254 254 … … 266 266 if (angle > 1) 267 267 angle = 1; 268 268 return acos(angle); 269 269 }; 270 270 … … 275 275 void Vector::RotateVector(const Vector *axis, const double alpha) 276 276 { 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 277 Vector a,y; 278 // normalise this vector with respect to axis 279 a.CopyVector(this); 280 a.Scale(Projection(axis)); 281 SubtractVector(&a); 282 // construct normal vector 283 y.MakeNormalVector(axis,this); 284 y.Scale(Norm()); 285 // scale normal vector by sine and this vector by cosine 286 y.Scale(sin(alpha)); 287 Scale(cos(alpha)); 288 // add scaled normal vector onto this vector 289 AddVector(&y); 290 // add part in axis direction 291 AddVector(&a); 292 292 }; 293 293 … … 299 299 Vector& operator+=(Vector& a, const Vector& b) 300 300 { 301 302 301 a.AddVector(&b); 302 return a; 303 303 }; 304 304 /** factor each component of \a a times a double \a m. … … 309 309 Vector& operator*=(Vector& a, const double m) 310 310 { 311 312 313 }; 314 315 /** Sums two vectors \a 311 a.Scale(m); 312 return a; 313 }; 314 315 /** Sums two vectors \a and \b component-wise. 316 316 * \param a first vector 317 317 * \param b second vector … … 320 320 Vector& operator+(const Vector& a, const Vector& b) 321 321 { 322 323 324 325 322 Vector *x = new Vector; 323 x->CopyVector(&a); 324 x->AddVector(&b); 325 return *x; 326 326 }; 327 327 … … 333 333 Vector& operator*(const Vector& a, const double m) 334 334 { 335 336 337 338 335 Vector *x = new Vector; 336 x->CopyVector(&a); 337 x->Scale(m); 338 return *x; 339 339 }; 340 340 … … 345 345 bool Vector::Output(ofstream *out) const 346 346 { 347 348 349 350 351 352 353 354 355 356 357 347 if (out != NULL) { 348 *out << "("; 349 for (int i=0;i<NDIM;i++) { 350 *out << x[i]; 351 if (i != 2) 352 *out << ","; 353 } 354 *out << ")"; 355 return true; 356 } else 357 return false; 358 358 }; 359 359 360 360 ostream& operator<<(ostream& ost,Vector& m) 361 361 { 362 363 364 365 366 367 368 369 362 ost << "("; 363 for (int i=0;i<NDIM;i++) { 364 ost << m.x[i]; 365 if (i != 2) 366 ost << ","; 367 } 368 ost << ")"; 369 return ost; 370 370 }; 371 371 … … 375 375 void Vector::Scale(double **factor) 376 376 { 377 378 377 for (int i=NDIM;i--;) 378 x[i] *= (*factor)[i]; 379 379 }; 380 380 381 381 void Vector::Scale(double *factor) 382 382 { 383 384 383 for (int i=NDIM;i--;) 384 x[i] *= *factor; 385 385 }; 386 386 387 387 void Vector::Scale(double factor) 388 388 { 389 390 389 for (int i=NDIM;i--;) 390 x[i] *= factor; 391 391 }; 392 392 … … 396 396 void Vector::Translate(const Vector *trans) 397 397 { 398 399 398 for (int i=NDIM;i--;) 399 x[i] += trans->x[i]; 400 400 }; 401 401 … … 405 405 void Vector::MatrixMultiplication(double *M) 406 406 { 407 408 409 410 411 412 413 414 407 Vector C; 408 // do the matrix multiplication 409 C.x[0] = M[0]*x[0]+M[3]*x[1]+M[6]*x[2]; 410 C.x[1] = M[1]*x[0]+M[4]*x[1]+M[7]*x[2]; 411 C.x[2] = M[2]*x[0]+M[5]*x[1]+M[8]*x[2]; 412 // transfer the result into this 413 for (int i=NDIM;i--;) 414 x[i] = C.x[i]; 415 415 }; 416 416 … … 447 447 void Vector::InverseMatrixMultiplication(double *A) 448 448 { 449 450 451 452 453 454 455 if (fabs(detA) > MYEPSILON) {;// RDET3(A) yields precisely zero if A irregular456 457 B[0] = detAReci*RDET2(A[4],A[5],A[7],A[8]);// A_11458 B[1] = -detAReci*RDET2(A[1],A[2],A[7],A[8]);// A_12459 B[2] = detAReci*RDET2(A[1],A[2],A[4],A[5]);// A_13460 B[3] = -detAReci*RDET2(A[3],A[5],A[6],A[8]);// A_21461 B[4] = detAReci*RDET2(A[0],A[2],A[6],A[8]);// A_22462 B[5] = -detAReci*RDET2(A[0],A[2],A[3],A[5]);// A_23463 B[6] = detAReci*RDET2(A[3],A[4],A[6],A[7]);// A_31464 B[7] = -detAReci*RDET2(A[0],A[1],A[6],A[7]);// A_32465 B[8] = detAReci*RDET2(A[0],A[1],A[3],A[4]);// A_33466 467 468 469 470 471 472 473 474 475 476 449 Vector C; 450 double B[NDIM*NDIM]; 451 double detA = RDET3(A); 452 double detAReci; 453 454 // calculate the inverse B 455 if (fabs(detA) > MYEPSILON) {; // RDET3(A) yields precisely zero if A irregular 456 detAReci = 1./detA; 457 B[0] = detAReci*RDET2(A[4],A[5],A[7],A[8]); // A_11 458 B[1] = -detAReci*RDET2(A[1],A[2],A[7],A[8]); // A_12 459 B[2] = detAReci*RDET2(A[1],A[2],A[4],A[5]); // A_13 460 B[3] = -detAReci*RDET2(A[3],A[5],A[6],A[8]); // A_21 461 B[4] = detAReci*RDET2(A[0],A[2],A[6],A[8]); // A_22 462 B[5] = -detAReci*RDET2(A[0],A[2],A[3],A[5]); // A_23 463 B[6] = detAReci*RDET2(A[3],A[4],A[6],A[7]); // A_31 464 B[7] = -detAReci*RDET2(A[0],A[1],A[6],A[7]); // A_32 465 B[8] = detAReci*RDET2(A[0],A[1],A[3],A[4]); // A_33 466 467 // do the matrix multiplication 468 C.x[0] = B[0]*x[0]+B[3]*x[1]+B[6]*x[2]; 469 C.x[1] = B[1]*x[0]+B[4]*x[1]+B[7]*x[2]; 470 C.x[2] = B[2]*x[0]+B[5]*x[1]+B[8]*x[2]; 471 // transfer the result into this 472 for (int i=NDIM;i--;) 473 x[i] = C.x[i]; 474 } else { 475 cerr << "ERROR: inverse of matrix does not exists!" << endl; 476 } 477 477 }; 478 478 … … 487 487 void Vector::LinearCombinationOfVectors(const Vector *x1, const Vector *x2, const Vector *x3, double *factors) 488 488 { 489 490 489 for(int i=NDIM;i--;) 490 x[i] = factors[0]*x1->x[i] + factors[1]*x2->x[i] + factors[2]*x3->x[i]; 491 491 }; 492 492 … … 496 496 void Vector::Mirror(const Vector *n) 497 497 { 498 499 projection = ScalarProduct(n)/n->ScalarProduct(n);// remove constancy from n (keep as logical one)500 501 502 503 504 505 506 507 508 498 double projection; 499 projection = ScalarProduct(n)/n->ScalarProduct(n); // remove constancy from n (keep as logical one) 500 // withdraw projected vector twice from original one 501 cout << Verbose(1) << "Vector: "; 502 Output((ofstream *)&cout); 503 cout << "\t"; 504 for (int i=NDIM;i--;) 505 x[i] -= 2.*projection*n->x[i]; 506 cout << "Projected vector: "; 507 Output((ofstream *)&cout); 508 cout << endl; 509 509 }; 510 510 … … 518 518 bool Vector::MakeNormalVector(const Vector *y1, const Vector *y2, const Vector *y3) 519 519 { 520 521 522 523 524 525 526 527 528 529 530 // 531 // 532 // 533 // 534 // 535 // 536 537 538 539 540 541 542 520 Vector x1, x2; 521 522 x1.CopyVector(y1); 523 x1.SubtractVector(y2); 524 x2.CopyVector(y3); 525 x2.SubtractVector(y2); 526 if ((fabs(x1.Norm()) < MYEPSILON) || (fabs(x2.Norm()) < MYEPSILON) || (fabs(x1.Angle(&x2)) < MYEPSILON)) { 527 cout << Verbose(4) << "Given vectors are linear dependent." << endl; 528 return false; 529 } 530 // cout << Verbose(4) << "relative, first plane coordinates:"; 531 // x1.Output((ofstream *)&cout); 532 // cout << endl; 533 // cout << Verbose(4) << "second plane coordinates:"; 534 // x2.Output((ofstream *)&cout); 535 // cout << endl; 536 537 this->x[0] = (x1.x[1]*x2.x[2] - x1.x[2]*x2.x[1]); 538 this->x[1] = (x1.x[2]*x2.x[0] - x1.x[0]*x2.x[2]); 539 this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]); 540 Normalize(); 541 542 return true; 543 543 }; 544 544 … … 554 554 bool Vector::MakeNormalVector(const Vector *y1, const Vector *y2) 555 555 { 556 557 558 559 560 561 562 563 564 // 565 // 566 // 567 // 568 // 569 // 570 571 572 573 574 575 576 556 Vector x1,x2; 557 x1.CopyVector(y1); 558 x2.CopyVector(y2); 559 Zero(); 560 if ((fabs(x1.Norm()) < MYEPSILON) || (fabs(x2.Norm()) < MYEPSILON) || (fabs(x1.Angle(&x2)) < MYEPSILON)) { 561 cout << Verbose(4) << "Given vectors are linear dependent." << endl; 562 return false; 563 } 564 // cout << Verbose(4) << "relative, first plane coordinates:"; 565 // x1.Output((ofstream *)&cout); 566 // cout << endl; 567 // cout << Verbose(4) << "second plane coordinates:"; 568 // x2.Output((ofstream *)&cout); 569 // cout << endl; 570 571 this->x[0] = (x1.x[1]*x2.x[2] - x1.x[2]*x2.x[1]); 572 this->x[1] = (x1.x[2]*x2.x[0] - x1.x[0]*x2.x[2]); 573 this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]); 574 Normalize(); 575 576 return true; 577 577 }; 578 578 … … 584 584 bool Vector::MakeNormalVector(const Vector *y1) 585 585 { 586 587 588 589 590 591 592 593 594 586 bool result = false; 587 Vector x1; 588 x1.CopyVector(y1); 589 x1.Scale(x1.Projection(this)); 590 SubtractVector(&x1); 591 for (int i=NDIM;i--;) 592 result = result || (fabs(x[i]) > MYEPSILON); 593 594 return result; 595 595 }; 596 596 … … 603 603 bool Vector::GetOneNormalVector(const Vector *GivenVector) 604 604 { 605 606 int Last = 0;// count the number of non-zero entries in vector607 int j;// loop variables608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 case 3:// threecomponent system623 case 2:// two component system624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 605 int Components[NDIM]; // contains indices of non-zero components 606 int Last = 0; // count the number of non-zero entries in vector 607 int j; // loop variables 608 double norm; 609 610 cout << Verbose(4); 611 GivenVector->Output((ofstream *)&cout); 612 cout << endl; 613 for (j=NDIM;j--;) 614 Components[j] = -1; 615 // find two components != 0 616 for (j=0;j<NDIM;j++) 617 if (fabs(GivenVector->x[j]) > MYEPSILON) 618 Components[Last++] = j; 619 cout << Verbose(4) << Last << " Components != 0: (" << Components[0] << "," << Components[1] << "," << Components[2] << ")" << endl; 620 621 switch(Last) { 622 case 3: // threecomponent system 623 case 2: // two component system 624 norm = sqrt(1./(GivenVector->x[Components[1]]*GivenVector->x[Components[1]]) + 1./(GivenVector->x[Components[0]]*GivenVector->x[Components[0]])); 625 x[Components[2]] = 0.; 626 // in skp both remaining parts shall become zero but with opposite sign and third is zero 627 x[Components[1]] = -1./GivenVector->x[Components[1]] / norm; 628 x[Components[0]] = 1./GivenVector->x[Components[0]] / norm; 629 return true; 630 break; 631 case 1: // one component system 632 // set sole non-zero component to 0, and one of the other zero component pendants to 1 633 x[(Components[0]+2)%NDIM] = 0.; 634 x[(Components[0]+1)%NDIM] = 1.; 635 x[Components[0]] = 0.; 636 return true; 637 break; 638 default: 639 return false; 640 } 641 641 }; 642 642 … … 649 649 double Vector::CutsPlaneAt(Vector *A, Vector *B, Vector *C) 650 650 { 651 // 652 // 653 // 654 // 655 // 656 651 // cout << Verbose(3) << "For comparison: "; 652 // cout << "A " << A->Projection(this) << "\t"; 653 // cout << "B " << B->Projection(this) << "\t"; 654 // cout << "C " << C->Projection(this) << "\t"; 655 // cout << endl; 656 return A->Projection(this); 657 657 }; 658 658 … … 664 664 bool Vector::LSQdistance(Vector **vectors, int num) 665 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 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 666 int j; 667 668 for (j=0;j<num;j++) { 669 cout << Verbose(1) << j << "th atom's vector: "; 670 (vectors[j])->Output((ofstream *)&cout); 671 cout << endl; 672 } 673 674 int np = 3; 675 struct LSQ_params par; 676 677 const gsl_multimin_fminimizer_type *T = 678 gsl_multimin_fminimizer_nmsimplex; 679 gsl_multimin_fminimizer *s = NULL; 680 gsl_vector *ss, *y; 681 gsl_multimin_function minex_func; 682 683 size_t iter = 0, i; 684 int status; 685 double size; 686 687 /* Initial vertex size vector */ 688 ss = gsl_vector_alloc (np); 689 y = gsl_vector_alloc (np); 690 691 /* Set all step sizes to 1 */ 692 gsl_vector_set_all (ss, 1.0); 693 694 /* Starting point */ 695 par.vectors = vectors; 696 par.num = num; 697 698 for (i=NDIM;i--;) 699 gsl_vector_set(y, i, (vectors[0]->x[i] - vectors[1]->x[i])/2.); 700 701 /* Initialize method and iterate */ 702 minex_func.f = &LSQ; 703 minex_func.n = np; 704 minex_func.params = (void *)∥ 705 706 s = gsl_multimin_fminimizer_alloc (T, np); 707 gsl_multimin_fminimizer_set (s, &minex_func, y, ss); 708 709 do 710 { 711 iter++; 712 status = gsl_multimin_fminimizer_iterate(s); 713 714 if (status) 715 break; 716 717 size = gsl_multimin_fminimizer_size (s); 718 status = gsl_multimin_test_size (size, 1e-2); 719 720 if (status == GSL_SUCCESS) 721 { 722 printf ("converged to minimum at\n"); 723 } 724 725 printf ("%5d ", (int)iter); 726 for (i = 0; i < (size_t)np; i++) 727 { 728 printf ("%10.3e ", gsl_vector_get (s->x, i)); 729 } 730 printf ("f() = %7.3f size = %.3f\n", s->fval, size); 731 } 732 while (status == GSL_CONTINUE && iter < 100); 733 734 for (i=(size_t)np;i--;) 735 this->x[i] = gsl_vector_get(s->x, i); 736 gsl_vector_free(y); 737 gsl_vector_free(ss); 738 gsl_multimin_fminimizer_free (s); 739 740 return true; 741 741 }; 742 742 … … 746 746 void Vector::AddVector(const Vector *y) 747 747 { 748 749 748 for (int i=NDIM;i--;) 749 this->x[i] += y->x[i]; 750 750 } 751 751 … … 755 755 void Vector::SubtractVector(const Vector *y) 756 756 { 757 758 757 for (int i=NDIM;i--;) 758 this->x[i] -= y->x[i]; 759 759 } 760 760 … … 764 764 void Vector::CopyVector(const Vector *y) 765 765 { 766 767 766 for (int i=NDIM;i--;) 767 this->x[i] = y->x[i]; 768 768 } 769 769 … … 775 775 void Vector::AskPosition(double *cell_size, bool check) 776 776 { 777 778 779 780 781 782 783 784 785 777 char coords[3] = {'x','y','z'}; 778 int j = -1; 779 for (int i=0;i<3;i++) { 780 j += i+1; 781 do { 782 cout << Verbose(0) << coords[i] << "[0.." << cell_size[j] << "]: "; 783 cin >> x[i]; 784 } while (((x[i] < 0) || (x[i] >= cell_size[j])) && (check)); 785 } 786 786 }; 787 787 … … 803 803 bool Vector::SolveSystem(Vector *x1, Vector *x2, Vector *y, double alpha, double beta, double c) 804 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 x[0] =A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2];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 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 }; 805 double D1,D2,D3,E1,E2,F1,F2,F3,p,q=0., A, B1, B2, C; 806 double ang; // angle on testing 807 double sign[3]; 808 int i,j,k; 809 A = cos(alpha) * x1->Norm() * c; 810 B1 = cos(beta + M_PI/2.) * y->Norm() * c; 811 B2 = cos(beta) * x2->Norm() * c; 812 C = c * c; 813 cout << Verbose(2) << "A " << A << "\tB " << B1 << "\tC " << C << endl; 814 int flag = 0; 815 if (fabs(x1->x[0]) < MYEPSILON) { // check for zero components for the later flipping and back-flipping 816 if (fabs(x1->x[1]) > MYEPSILON) { 817 flag = 1; 818 } else if (fabs(x1->x[2]) > MYEPSILON) { 819 flag = 2; 820 } else { 821 return false; 822 } 823 } 824 switch (flag) { 825 default: 826 case 0: 827 break; 828 case 2: 829 flip(&x1->x[0],&x1->x[1]); 830 flip(&x2->x[0],&x2->x[1]); 831 flip(&y->x[0],&y->x[1]); 832 //flip(&x[0],&x[1]); 833 flip(&x1->x[1],&x1->x[2]); 834 flip(&x2->x[1],&x2->x[2]); 835 flip(&y->x[1],&y->x[2]); 836 //flip(&x[1],&x[2]); 837 case 1: 838 flip(&x1->x[0],&x1->x[1]); 839 flip(&x2->x[0],&x2->x[1]); 840 flip(&y->x[0],&y->x[1]); 841 //flip(&x[0],&x[1]); 842 flip(&x1->x[1],&x1->x[2]); 843 flip(&x2->x[1],&x2->x[2]); 844 flip(&y->x[1],&y->x[2]); 845 //flip(&x[1],&x[2]); 846 break; 847 } 848 // now comes the case system 849 D1 = -y->x[0]/x1->x[0]*x1->x[1]+y->x[1]; 850 D2 = -y->x[0]/x1->x[0]*x1->x[2]+y->x[2]; 851 D3 = y->x[0]/x1->x[0]*A-B1; 852 cout << Verbose(2) << "D1 " << D1 << "\tD2 " << D2 << "\tD3 " << D3 << "\n"; 853 if (fabs(D1) < MYEPSILON) { 854 cout << Verbose(2) << "D1 == 0!\n"; 855 if (fabs(D2) > MYEPSILON) { 856 cout << Verbose(3) << "D2 != 0!\n"; 857 x[2] = -D3/D2; 858 E1 = A/x1->x[0] + x1->x[2]/x1->x[0]*D3/D2; 859 E2 = -x1->x[1]/x1->x[0]; 860 cout << Verbose(3) << "E1 " << E1 << "\tE2 " << E2 << "\n"; 861 F1 = E1*E1 + 1.; 862 F2 = -E1*E2; 863 F3 = E1*E1 + D3*D3/(D2*D2) - C; 864 cout << Verbose(3) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n"; 865 if (fabs(F1) < MYEPSILON) { 866 cout << Verbose(4) << "F1 == 0!\n"; 867 cout << Verbose(4) << "Gleichungssystem linear\n"; 868 x[1] = F3/(2.*F2); 869 } else { 870 p = F2/F1; 871 q = p*p - F3/F1; 872 cout << Verbose(4) << "p " << p << "\tq " << q << endl; 873 if (q < 0) { 874 cout << Verbose(4) << "q < 0" << endl; 875 return false; 876 } 877 x[1] = p + sqrt(q); 878 } 879 x[0] = A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2]; 880 } else { 881 cout << Verbose(2) << "Gleichungssystem unterbestimmt\n"; 882 return false; 883 } 884 } else { 885 E1 = A/x1->x[0]+x1->x[1]/x1->x[0]*D3/D1; 886 E2 = x1->x[1]/x1->x[0]*D2/D1 - x1->x[2]; 887 cout << Verbose(2) << "E1 " << E1 << "\tE2 " << E2 << "\n"; 888 F1 = E2*E2 + D2*D2/(D1*D1) + 1.; 889 F2 = -(E1*E2 + D2*D3/(D1*D1)); 890 F3 = E1*E1 + D3*D3/(D1*D1) - C; 891 cout << Verbose(2) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n"; 892 if (fabs(F1) < MYEPSILON) { 893 cout << Verbose(3) << "F1 == 0!\n"; 894 cout << Verbose(3) << "Gleichungssystem linear\n"; 895 x[2] = F3/(2.*F2); 896 } else { 897 p = F2/F1; 898 q = p*p - F3/F1; 899 cout << Verbose(3) << "p " << p << "\tq " << q << endl; 900 if (q < 0) { 901 cout << Verbose(3) << "q < 0" << endl; 902 return false; 903 } 904 x[2] = p + sqrt(q); 905 } 906 x[1] = (-D2 * x[2] - D3)/D1; 907 x[0] = A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2]; 908 } 909 switch (flag) { // back-flipping 910 default: 911 case 0: 912 break; 913 case 2: 914 flip(&x1->x[0],&x1->x[1]); 915 flip(&x2->x[0],&x2->x[1]); 916 flip(&y->x[0],&y->x[1]); 917 flip(&x[0],&x[1]); 918 flip(&x1->x[1],&x1->x[2]); 919 flip(&x2->x[1],&x2->x[2]); 920 flip(&y->x[1],&y->x[2]); 921 flip(&x[1],&x[2]); 922 case 1: 923 flip(&x1->x[0],&x1->x[1]); 924 flip(&x2->x[0],&x2->x[1]); 925 flip(&y->x[0],&y->x[1]); 926 //flip(&x[0],&x[1]); 927 flip(&x1->x[1],&x1->x[2]); 928 flip(&x2->x[1],&x2->x[2]); 929 flip(&y->x[1],&y->x[2]); 930 flip(&x[1],&x[2]); 931 break; 932 } 933 // one z component is only determined by its radius (without sign) 934 // thus check eight possible sign flips and determine by checking angle with second vector 935 for (i=0;i<8;i++) { 936 // set sign vector accordingly 937 for (j=2;j>=0;j--) { 938 k = (i & pot(2,j)) << j; 939 cout << Verbose(2) << "k " << k << "\tpot(2,j) " << pot(2,j) << endl; 940 sign[j] = (k == 0) ? 1. : -1.; 941 } 942 cout << Verbose(2) << i << ": sign matrix is " << sign[0] << "\t" << sign[1] << "\t" << sign[2] << "\n"; 943 // apply sign matrix 944 for (j=NDIM;j--;) 945 x[j] *= sign[j]; 946 // calculate angle and check 947 ang = x2->Angle (this); 948 cout << Verbose(1) << i << "th angle " << ang << "\tbeta " << cos(beta) << " :\t"; 949 if (fabs(ang - cos(beta)) < MYEPSILON) { 950 break; 951 } 952 // unapply sign matrix (is its own inverse) 953 for (j=NDIM;j--;) 954 x[j] *= sign[j]; 955 } 956 return true; 957 }; -
src/vector.hpp
r205ccd r042f82 8 8 */ 9 9 class Vector { 10 11 10 public: 11 double x[NDIM]; 12 12 13 14 15 13 Vector(); 14 Vector(double x1, double x2, double x3); 15 ~Vector(); 16 16 17 18 19 20 21 22 23 24 17 double Distance(const Vector *y) const; 18 double DistanceSquared(const Vector *y) const; 19 double PeriodicDistance(const Vector *y, const double *cell_size) const; 20 double PeriodicDistanceSquared(const Vector *y, const double *cell_size) const; 21 double ScalarProduct(const Vector *y) const; 22 double Projection(const Vector *y) const; 23 double Norm() const ; 24 double Angle(const Vector *y) const; 25 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 26 void AddVector(const Vector *y); 27 void SubtractVector(const Vector *y); 28 void CopyVector(const Vector *y); 29 void RotateVector(const Vector *y, const double alpha); 30 void VectorProduct(const Vector *y); 31 void ProjectOntoPlane(const Vector *y); 32 void Zero(); 33 void One(double one); 34 void Init(double x1, double x2, double x3); 35 void Normalize(); 36 void Translate(const Vector *x); 37 void Mirror(const Vector *x); 38 void Scale(double **factor); 39 void Scale(double *factor); 40 void Scale(double factor); 41 void MatrixMultiplication(double *M); 42 double * InverseMatrix(double *A); 43 void InverseMatrixMultiplication(double *M); 44 void KeepPeriodic(ofstream *out, double *matrix); 45 void LinearCombinationOfVectors(const Vector *x1, const Vector *x2, const Vector *x3, double *factors); 46 double CutsPlaneAt(Vector *A, Vector *B, Vector *C); 47 bool GetOneNormalVector(const Vector *x1); 48 bool MakeNormalVector(const Vector *y1); 49 bool MakeNormalVector(const Vector *y1, const Vector *y2); 50 bool MakeNormalVector(const Vector *x1, const Vector *x2, const Vector *x3); 51 bool SolveSystem(Vector *x1, Vector *x2, Vector *y, double alpha, double beta, double c); 52 bool LSQdistance(Vector **vectors, int dim); 53 void AskPosition(double *cell_size, bool check); 54 bool Output(ofstream *out) const; 55 55 }; 56 56 -
src/verbose.cpp
r205ccd r042f82 7 7 ostream& Verbose::print (ostream &ost) const 8 8 { 9 10 11 12 9 for (int i=Verbosity;i--;) 10 ost.put('\t'); 11 //cout << "Verbose(.) called." << endl; 12 return ost; 13 13 }; 14 14 … … 22 22 ostream& operator<<(ostream& ost,const Verbose& m) 23 23 { 24 24 return m.print(ost); 25 25 }; 26 26 … … 33 33 ostream& Binary::print (ostream &ost) const 34 34 { 35 36 37 38 39 40 41 42 43 44 45 46 35 int bits = 1, counter = 1; 36 while ((bits = 1 << counter) < BinaryNumber) 37 counter++; 38 for (int i=0;i<counter-1;i++) { 39 if ((BinaryNumber & (1 << i)) == 0) 40 ost.put('0'); 41 else 42 ost.put('1'); 43 } 44 ost.put('b'); 45 //cout << "Binary(.) called." << endl; 46 return ost; 47 47 }; 48 48 … … 56 56 ostream& operator<<(ostream& ost,const Binary& m) 57 57 { 58 58 return m.print(ost); 59 59 };
Note:
See TracChangeset
for help on using the changeset viewer.