- Timestamp:
- Jul 23, 2009, 1:53:01 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, Candidate_v1.7.0, 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:
- 51c910
- Parents:
- a5b2c3a
- Location:
- src
- Files:
-
- 2 edited
-
builder.cpp (modified) (22 diffs)
-
molecules.cpp (modified) (90 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/builder.cpp
ra5b2c3a r375b458 15 15 * \section about About the Program 16 16 * 17 * Molecuilder is a short program, written in C++, that enables the construction of a coordinate set for the18 * atoms making up an molecule by the successive statement of binding angles and distances and referencing to19 * already constructed atoms.17 * Molecuilder is a short program, written in C++, that enables the construction of a coordinate set for the 18 * atoms making up an molecule by the successive statement of binding angles and distances and referencing to 19 * already constructed atoms. 20 20 * 21 * A configuration file may be written that is compatible to the format used by PCP - a parallel Car-Parrinello22 * molecular dynamics implementation.21 * A configuration file may be written that is compatible to the format used by PCP - a parallel Car-Parrinello 22 * molecular dynamics implementation. 23 23 * 24 24 * \section install Installation 25 25 * 26 * Installation should without problems succeed as follows:27 * -# ./configure (or: mkdir build;mkdir run;cd build; ../configure --bindir=../run)28 * -# make29 * -# make install26 * 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 * Further useful commands are32 * -# make clean uninstall: deletes .o-files and removes executable from the given binary directory\n33 * -# make doxygen-doc: Creates these html pages out of the documented source31 * 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 * The program can be executed by running: ./molecuilder37 * The program can be executed by running: ./molecuilder 38 38 * 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 on41 * later re-execution.39 * Note, that it uses a database, called "elements.db", in the executable's directory. If the file is not found, 40 * it is created and any given data on elements of the periodic table will be stored therein and re-used on 41 * later re-execution. 42 42 * 43 43 * \section ref References 44 44 * 45 * For the special configuration file format, see the documentation of pcp.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 atom *first, *second, *third, *fourth;66 Vector **atoms;67 Vector x,y,z,n;// coordinates for absolute point in cell volume68 double a,b,c;69 char choice;// menu choice char70 bool valid;71 72 cout << Verbose(0) << "===========ADD ATOM============================" << endl;73 cout << Verbose(0) << " a - state absolute coordinates of atom" << endl;74 cout << Verbose(0) << " b - state relative coordinates of atom wrt to reference point" << endl;75 cout << Verbose(0) << " c - state relative coordinates of atom wrt to already placed atom" << endl;76 cout << Verbose(0) << " d - state two atoms, two angles and a distance" << endl;77 cout << Verbose(0) << " e - least square distance position to a set of atoms" << endl;78 cout << Verbose(0) << "all else - go back" << endl;79 cout << Verbose(0) << "===============================================" << endl;80 cout << Verbose(0) << "Note: Specifiy angles in degrees not multiples of Pi!" << endl;81 cout << Verbose(0) << "INPUT: ";82 cin >> choice;83 84 switch (choice) {65 atom *first, *second, *third, *fourth; 66 Vector **atoms; 67 Vector x,y,z,n; // coordinates for absolute point in cell volume 68 double a,b,c; 69 char choice; // menu choice char 70 bool valid; 71 72 cout << Verbose(0) << "===========ADD ATOM============================" << endl; 73 cout << Verbose(0) << " a - state absolute coordinates of atom" << endl; 74 cout << Verbose(0) << " b - state relative coordinates of atom wrt to reference point" << endl; 75 cout << Verbose(0) << " c - state relative coordinates of atom wrt to already placed atom" << endl; 76 cout << Verbose(0) << " d - state two atoms, two angles and a distance" << endl; 77 cout << Verbose(0) << " e - least square distance position to a set of atoms" << endl; 78 cout << Verbose(0) << "all else - go back" << endl; 79 cout << Verbose(0) << "===============================================" << endl; 80 cout << Verbose(0) << "Note: Specifiy angles in degrees not multiples of Pi!" << endl; 81 cout << Verbose(0) << "INPUT: "; 82 cin >> choice; 83 84 switch (choice) { 85 85 default: 86 86 cout << Verbose(0) << "Not a valid choice." << endl; 87 87 break; 88 case 'a': // absolute coordinates of atom88 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(); // give type93 mol->AddAtom(first); // add to molecule94 break;95 96 case 'b': // relative coordinates of atom wrt to reference point92 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(); // give type109 mol->AddAtom(first); // add to molecule110 break;111 112 case 'c': // relative coordinates of atom wrt to already placed atom108 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(); // give type125 mol->AddAtom(first); // add to molecule124 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(); // give type227 mol->AddAtom(first); // add to molecule228 break;229 230 case 'e': // least square distance position to a set of atoms226 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(); // give type251 mol->AddAtom(first); // add to molecule250 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 break;257 };256 break; 257 }; 258 258 }; 259 259 … … 263 263 static void CenterAtoms(molecule *mol) 264 264 { 265 Vector x, y, helper;266 char choice;// menu choice char267 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 positive297 mol->Translate(&y); // translate by boundary298 helper.CopyVector(&y);299 helper.Scale(2.);300 helper.AddVector(&x);301 mol->SetBoxDimension(&helper);// update Box of atoms by boundary302 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 // center310 mol->CenterInBox((ofstream *)&cout, &x);311 // update Box of atoms by boundary312 mol->SetBoxDimension(&x);313 break;314 }265 Vector x, y, helper; 266 char choice; // menu choice char 267 268 cout << Verbose(0) << "===========CENTER ATOMS=========================" << endl; 269 cout << Verbose(0) << " a - on origin" << endl; 270 cout << Verbose(0) << " b - on center of gravity" << endl; 271 cout << Verbose(0) << " c - within box with additional boundary" << endl; 272 cout << Verbose(0) << " d - within given simulation box" << endl; 273 cout << Verbose(0) << "all else - go back" << endl; 274 cout << Verbose(0) << "===============================================" << endl; 275 cout << Verbose(0) << "INPUT: "; 276 cin >> choice; 277 278 switch (choice) { 279 default: 280 cout << Verbose(0) << "Not a valid choice." << endl; 281 break; 282 case 'a': 283 cout << Verbose(0) << "Centering atoms in config file on origin." << endl; 284 mol->CenterOrigin((ofstream *)&cout, &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, &x); 311 // update Box of atoms by boundary 312 mol->SetBoxDimension(&x); 313 break; 314 } 315 315 }; 316 316 … … 321 321 static void AlignAtoms(periodentafel *periode, molecule *mol) 322 322 { 323 atom *first, *second, *third;324 Vector x,n;325 char choice;// menu choice char326 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 plane340 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 plane347 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 plane352 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);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 atom *first, *second, *third;392 Vector n;393 char choice;// menu choice char394 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 plane407 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 plane414 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 plane419 first = mol->AskAtom("Enter first atom: ");420 second = mol->AskAtom("Enter second atom: ");421 422 n.CopyVector((const Vector *)&first->x);423 n.SubtractVector((const Vector *)&second->x);424 n.Normalize();425 break;426 };427 cout << Verbose(0) << "Normal vector: ";428 n.Output((ofstream *)&cout);429 cout << Verbose(0) << endl;430 mol->Mirror((const Vector *)&n);391 atom *first, *second, *third; 392 Vector n; 393 char choice; // menu choice char 394 395 cout << Verbose(0) << "===========MIRROR ATOMS=========================" << endl; 396 cout << Verbose(0) << " a - state three atoms defining mirror plane" << endl; 397 cout << Verbose(0) << " b - state normal vector of mirror plane" << endl; 398 cout << Verbose(0) << " c - state two atoms in normal direction" << endl; 399 cout << Verbose(0) << "all else - go back" << endl; 400 cout << Verbose(0) << "===============================================" << endl; 401 cout << Verbose(0) << "INPUT: "; 402 cin >> choice; 403 404 switch (choice) { 405 default: 406 case 'a': // three atoms defining mirror plane 407 first = mol->AskAtom("Enter first atom: "); 408 second = mol->AskAtom("Enter second atom: "); 409 third = mol->AskAtom("Enter third atom: "); 410 411 n.MakeNormalVector((const Vector *)&first->x,(const Vector *)&second->x,(const Vector *)&third->x); 412 break; 413 case 'b': // normal vector of mirror plane 414 cout << Verbose(0) << "Enter normal vector of mirror plane." << endl; 415 n.AskPosition(mol->cell_size,0); 416 n.Normalize(); 417 break; 418 case 'c': // three atoms defining mirror plane 419 first = mol->AskAtom("Enter first atom: "); 420 second = mol->AskAtom("Enter second atom: "); 421 422 n.CopyVector((const Vector *)&first->x); 423 n.SubtractVector((const Vector *)&second->x); 424 n.Normalize(); 425 break; 426 }; 427 cout << Verbose(0) << "Normal vector: "; 428 n.Output((ofstream *)&cout); 429 cout << Verbose(0) << endl; 430 mol->Mirror((const Vector *)&n); 431 431 }; 432 432 … … 436 436 static void RemoveAtoms(molecule *mol) 437 437 { 438 atom *first, *second, *third; 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 third = mol->AskAtom("Enter number of atom as reference point: "); 462 cout << Verbose(0) << "Enter radius: "; 463 cin >> tmp1; 464 first = mol->start; 465 second = first->next; 466 while(second != mol->end) { 467 first = second; 468 second = first->next; 469 if (first->x.DistanceSquared((const Vector *)&third->x) > tmp1*tmp1) // distance to first above radius ... 470 mol->RemoveAtom(first); 471 } 472 break; 473 case 'c': 474 cout << Verbose(0) << "Which axis is it: "; 475 cin >> axis; 476 cout << Verbose(0) << "Lower boundary: "; 477 cin >> tmp1; 478 cout << Verbose(0) << "Upper boundary: "; 479 cin >> tmp2; 480 first = mol->start; 438 atom *first, *second, *third; 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 third = mol->AskAtom("Enter number of atom as reference point: "); 462 cout << Verbose(0) << "Enter radius: "; 463 cin >> tmp1; 464 first = mol->start; 481 465 second = first->next; 482 466 while(second != mol->end) { 483 467 first = second; 484 468 second = first->next; 485 if ((first->x.x[axis] < tmp1) || (first->x.x[axis] > tmp2)) {// out of boundary ... 486 //cout << "Atom " << *first << " with " << first->x.x[axis] << " on axis " << axis << " is out of bounds [" << tmp1 << "," << tmp2 << "]." << endl; 487 mol->RemoveAtom(first); 488 } 489 } 490 break; 491 }; 492 //mol->Output((ofstream *)&cout); 493 choice = 'r'; 469 if (first->x.DistanceSquared((const Vector *)&third->x) > tmp1*tmp1) // distance to first above radius ... 470 mol->RemoveAtom(first); 471 } 472 break; 473 case 'c': 474 cout << Verbose(0) << "Which axis is it: "; 475 cin >> axis; 476 cout << Verbose(0) << "Lower boundary: "; 477 cin >> tmp1; 478 cout << Verbose(0) << "Upper boundary: "; 479 cin >> tmp2; 480 first = mol->start; 481 second = first->next; 482 while(second != mol->end) { 483 first = second; 484 second = first->next; 485 if ((first->x.x[axis] < tmp1) || (first->x.x[axis] > tmp2)) {// out of boundary ... 486 //cout << "Atom " << *first << " with " << first->x.x[axis] << " on axis " << axis << " is out of bounds [" << tmp1 << "," << tmp2 << "]." << endl; 487 mol->RemoveAtom(first); 488 } 489 } 490 break; 491 }; 492 //mol->Output((ofstream *)&cout); 493 choice = 'r'; 494 494 }; 495 495 … … 500 500 static void MeasureAtoms(periodentafel *periode, molecule *mol, config *configuration) 501 501 { 502 atom *first, *second, *third;503 Vector x,y;504 double min[256], tmp1, tmp2, tmp3;505 int Z;506 char choice;// menu choice char507 508 cout << Verbose(0) << "===========MEASURE ATOMS=========================" << endl;509 cout << Verbose(0) << " a - calculate bond length between one atom and all others" << endl;510 cout << Verbose(0) << " b - calculate bond length between two atoms" << endl;511 cout << Verbose(0) << " c - calculate bond angle" << endl;512 cout << Verbose(0) << " d - calculate principal axis of the system" << endl;513 cout << Verbose(0) << " e - calculate volume of the convex envelope" << endl;514 cout << Verbose(0) << " f - calculate temperature from current velocity" << endl;515 cout << Verbose(0) << " g - output all temperatures per step from velocities" << endl;516 cout << Verbose(0) << "all else - go back" << endl;517 cout << Verbose(0) << "===============================================" << endl;518 cout << Verbose(0) << "INPUT: ";519 cin >> choice;520 521 switch(choice) {522 default:523 cout << Verbose(1) << "Not a valid choice." << endl;524 break;525 case 'a':526 first = mol->AskAtom("Enter first atom: ");527 for (int i=MAX_ELEMENTS;i--;)528 min[i] = 0.;529 530 second = mol->start;531 while ((second->next != mol->end)) {532 second = second->next; // advance533 Z = second->type->Z;534 tmp1 = 0.;535 if (first != second) {536 x.CopyVector((const Vector *)&first->x);537 x.SubtractVector((const Vector *)&second->x);538 tmp1 = x.Norm();539 }540 if ((tmp1 != 0.) && ((min[Z] == 0.) || (tmp1 < min[Z]))) min[Z] = tmp1;541 //cout << Verbose(0) << "Bond length between Atom " << first->nr << " and " << second->nr << ": " << tmp1 << " a.u." << endl;542 }543 for (int i=MAX_ELEMENTS;i--;)544 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;545 break;546 547 case 'b':548 first = mol->AskAtom("Enter first atom: ");549 second = mol->AskAtom("Enter second atom: ");550 for (int i=NDIM;i--;)551 min[i] = 0.;552 x.CopyVector((const Vector *)&first->x);553 x.SubtractVector((const Vector *)&second->x);554 tmp1 = x.Norm();555 cout << Verbose(1) << "Distance vector is ";556 x.Output((ofstream *)&cout);557 cout << "." << endl << "Norm of distance is " << tmp1 << "." << endl;558 break;559 560 case 'c':561 cout << Verbose(0) << "Evaluating bond angle between three - first, central, last - atoms." << endl;562 first = mol->AskAtom("Enter first atom: ");563 second = mol->AskAtom("Enter central atom: ");564 third= mol->AskAtom("Enter last atom: ");565 tmp1 = tmp2 = tmp3 = 0.;566 x.CopyVector((const Vector *)&first->x);567 x.SubtractVector((const Vector *)&second->x);568 y.CopyVector((const Vector *)&third->x);569 y.SubtractVector((const Vector *)&second->x);570 cout << Verbose(0) << "Bond angle between first atom Nr." << first->nr << ", central atom Nr." << second->nr << " and last atom Nr." << third->nr << ": ";571 cout << Verbose(0) << (acos(x.ScalarProduct((const Vector *)&y)/(y.Norm()*x.Norm()))/M_PI*180.) << " degrees" << endl;572 break;573 case 'd':574 cout << Verbose(0) << "Evaluating prinicipal axis." << endl;575 cout << Verbose(0) << "Shall we rotate? [0/1]: ";576 cin >> Z;577 if ((Z >=0) && (Z <=1))578 mol->PrincipalAxisSystem((ofstream *)&cout, (bool)Z);579 else580 mol->PrincipalAxisSystem((ofstream *)&cout, false);581 break;582 case 'e':583 cout << Verbose(0) << "Evaluating volume of the convex envelope.";584 VolumeOfConvexEnvelope((ofstream *)&cout, NULL, configuration, NULL, mol);585 break;586 case 'f':587 mol->OutputTemperatureFromTrajectories((ofstream *)&cout, mol->MDSteps-1, mol->MDSteps, (ofstream *)&cout);588 break;589 case 'g':590 {591 char filename[255];592 cout << "Please enter filename: " << endl;593 cin >> filename;594 cout << Verbose(1) << "Storing temperatures in " << filename << "." << endl;595 ofstream *output = new ofstream(filename, ios::trunc);596 if (!mol->OutputTemperatureFromTrajectories((ofstream *)&cout, 0, mol->MDSteps, output))597 cout << Verbose(2) << "File could not be written." << endl;598 else599 cout << Verbose(2) << "File stored." << endl;600 output->close();601 delete(output);602 }603 break;604 }502 atom *first, *second, *third; 503 Vector x,y; 504 double min[256], tmp1, tmp2, tmp3; 505 int Z; 506 char choice; // menu choice char 507 508 cout << Verbose(0) << "===========MEASURE ATOMS=========================" << endl; 509 cout << Verbose(0) << " a - calculate bond length between one atom and all others" << endl; 510 cout << Verbose(0) << " b - calculate bond length between two atoms" << endl; 511 cout << Verbose(0) << " c - calculate bond angle" << endl; 512 cout << Verbose(0) << " d - calculate principal axis of the system" << endl; 513 cout << Verbose(0) << " e - calculate volume of the convex envelope" << endl; 514 cout << Verbose(0) << " f - calculate temperature from current velocity" << endl; 515 cout << Verbose(0) << " g - output all temperatures per step from velocities" << endl; 516 cout << Verbose(0) << "all else - go back" << endl; 517 cout << Verbose(0) << "===============================================" << endl; 518 cout << Verbose(0) << "INPUT: "; 519 cin >> choice; 520 521 switch(choice) { 522 default: 523 cout << Verbose(1) << "Not a valid choice." << endl; 524 break; 525 case 'a': 526 first = mol->AskAtom("Enter first atom: "); 527 for (int i=MAX_ELEMENTS;i--;) 528 min[i] = 0.; 529 530 second = mol->start; 531 while ((second->next != mol->end)) { 532 second = second->next; // advance 533 Z = second->type->Z; 534 tmp1 = 0.; 535 if (first != second) { 536 x.CopyVector((const Vector *)&first->x); 537 x.SubtractVector((const Vector *)&second->x); 538 tmp1 = x.Norm(); 539 } 540 if ((tmp1 != 0.) && ((min[Z] == 0.) || (tmp1 < min[Z]))) min[Z] = tmp1; 541 //cout << Verbose(0) << "Bond length between Atom " << first->nr << " and " << second->nr << ": " << tmp1 << " a.u." << endl; 542 } 543 for (int i=MAX_ELEMENTS;i--;) 544 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; 545 break; 546 547 case 'b': 548 first = mol->AskAtom("Enter first atom: "); 549 second = mol->AskAtom("Enter second atom: "); 550 for (int i=NDIM;i--;) 551 min[i] = 0.; 552 x.CopyVector((const Vector *)&first->x); 553 x.SubtractVector((const Vector *)&second->x); 554 tmp1 = x.Norm(); 555 cout << Verbose(1) << "Distance vector is "; 556 x.Output((ofstream *)&cout); 557 cout << "." << endl << "Norm of distance is " << tmp1 << "." << endl; 558 break; 559 560 case 'c': 561 cout << Verbose(0) << "Evaluating bond angle between three - first, central, last - atoms." << endl; 562 first = mol->AskAtom("Enter first atom: "); 563 second = mol->AskAtom("Enter central atom: "); 564 third = mol->AskAtom("Enter last atom: "); 565 tmp1 = tmp2 = tmp3 = 0.; 566 x.CopyVector((const Vector *)&first->x); 567 x.SubtractVector((const Vector *)&second->x); 568 y.CopyVector((const Vector *)&third->x); 569 y.SubtractVector((const Vector *)&second->x); 570 cout << Verbose(0) << "Bond angle between first atom Nr." << first->nr << ", central atom Nr." << second->nr << " and last atom Nr." << third->nr << ": "; 571 cout << Verbose(0) << (acos(x.ScalarProduct((const Vector *)&y)/(y.Norm()*x.Norm()))/M_PI*180.) << " degrees" << endl; 572 break; 573 case 'd': 574 cout << Verbose(0) << "Evaluating prinicipal axis." << endl; 575 cout << Verbose(0) << "Shall we rotate? [0/1]: "; 576 cin >> Z; 577 if ((Z >=0) && (Z <=1)) 578 mol->PrincipalAxisSystem((ofstream *)&cout, (bool)Z); 579 else 580 mol->PrincipalAxisSystem((ofstream *)&cout, false); 581 break; 582 case 'e': 583 cout << Verbose(0) << "Evaluating volume of the convex envelope."; 584 VolumeOfConvexEnvelope((ofstream *)&cout, NULL, configuration, NULL, mol); 585 break; 586 case 'f': 587 mol->OutputTemperatureFromTrajectories((ofstream *)&cout, mol->MDSteps-1, mol->MDSteps, (ofstream *)&cout); 588 break; 589 case 'g': 590 { 591 char filename[255]; 592 cout << "Please enter filename: " << endl; 593 cin >> filename; 594 cout << Verbose(1) << "Storing temperatures in " << filename << "." << endl; 595 ofstream *output = new ofstream(filename, ios::trunc); 596 if (!mol->OutputTemperatureFromTrajectories((ofstream *)&cout, 0, mol->MDSteps, output)) 597 cout << Verbose(2) << "File could not be written." << endl; 598 else 599 cout << Verbose(2) << "File stored." << endl; 600 output->close(); 601 delete(output); 602 } 603 break; 604 } 605 605 }; 606 606 … … 611 611 static void FragmentAtoms(molecule *mol, config *configuration) 612 612 { 613 int Order1;614 clock_t start, end;615 616 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl;617 cout << Verbose(0) << "What's the desired bond order: ";618 cin >> Order1;619 if (mol->first->next != mol->last) {// there are bonds620 start = clock();621 mol->FragmentMolecule((ofstream *)&cout, Order1, configuration);622 end = clock();623 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;624 } else625 cout << Verbose(0) << "Connection matrix has not yet been generated!" << endl;613 int Order1; 614 clock_t start, end; 615 616 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl; 617 cout << Verbose(0) << "What's the desired bond order: "; 618 cin >> Order1; 619 if (mol->first->next != mol->last) { // there are bonds 620 start = clock(); 621 mol->FragmentMolecule((ofstream *)&cout, Order1, configuration); 622 end = clock(); 623 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl; 624 } else 625 cout << Verbose(0) << "Connection matrix has not yet been generated!" << endl; 626 626 }; 627 627 … … 1053 1053 static void testroutine(MoleculeListClass *molecules) 1054 1054 { 1055 // the current test routine checks the functionality of the KeySet&Graph concept:1056 // We want to have a multiindex (the KeySet) describing a unique subgraph1055 // the current test routine checks the functionality of the KeySet&Graph concept: 1056 // We want to have a multiindex (the KeySet) describing a unique subgraph 1057 1057 int i, comp, counter=0; 1058 1058 … … 1067 1067 atom *Walker = mol->start; 1068 1068 1069 // generate some KeySets1070 cout << "Generating KeySets." << endl;1071 KeySet TestSets[mol->AtomCount+1];1072 i=1;1073 while (Walker->next != mol->end) {1074 Walker = Walker->next;1075 for (int j=0;j<i;j++) {1076 TestSets[j].insert(Walker->nr);1077 }1078 i++;1079 }1080 cout << "Testing insertion of already present item in KeySets." << endl;1081 KeySetTestPair test;1082 test = TestSets[mol->AtomCount-1].insert(Walker->nr);1083 if (test.second) {1084 cout << Verbose(1) << "Insertion worked?!" << endl;1085 } else {1086 cout << Verbose(1) << "Insertion rejected: Present object is " << (*test.first) << "." << endl;1087 }1088 TestSets[mol->AtomCount].insert(mol->end->previous->nr);1089 TestSets[mol->AtomCount].insert(mol->end->previous->previous->previous->nr);1090 1091 // constructing Graph structure1092 cout << "Generating Subgraph class." << endl;1093 Graph Subgraphs;1094 1095 // insert KeySets into Subgraphs1096 cout << "Inserting KeySets into Subgraph class." << endl;1097 for (int j=0;j<mol->AtomCount;j++) {1098 Subgraphs.insert(GraphPair (TestSets[j],pair<int, double>(counter++, 1.)));1099 }1100 cout << "Testing insertion of already present item in Subgraph." << endl;1101 GraphTestPair test2;1102 test2 = Subgraphs.insert(GraphPair (TestSets[mol->AtomCount],pair<int, double>(counter++, 1.)));1103 if (test2.second) {1104 cout << Verbose(1) << "Insertion worked?!" << endl;1105 } else {1106 cout << Verbose(1) << "Insertion rejected: Present object is " << (*(test2.first)).second.first << "." << endl;1107 }1108 1109 // show graphs1110 cout << "Showing Subgraph's contents, checking that it's sorted." << endl;1111 Graph::iterator A = Subgraphs.begin();1112 while (A !=Subgraphs.end()) {1113 cout << (*A).second.first << ": ";1114 KeySet::iterator key = (*A).first.begin();1115 comp = -1;1116 while (key != (*A).first.end()) {1117 if ((*key) > comp)1118 cout << (*key) << " ";1119 else1120 cout << (*key) << "! ";1121 comp = (*key);1122 key++;1123 }1124 cout << endl;1125 A++;1126 }1127 delete(mol);1069 // generate some KeySets 1070 cout << "Generating KeySets." << endl; 1071 KeySet TestSets[mol->AtomCount+1]; 1072 i=1; 1073 while (Walker->next != mol->end) { 1074 Walker = Walker->next; 1075 for (int j=0;j<i;j++) { 1076 TestSets[j].insert(Walker->nr); 1077 } 1078 i++; 1079 } 1080 cout << "Testing insertion of already present item in KeySets." << endl; 1081 KeySetTestPair test; 1082 test = TestSets[mol->AtomCount-1].insert(Walker->nr); 1083 if (test.second) { 1084 cout << Verbose(1) << "Insertion worked?!" << endl; 1085 } else { 1086 cout << Verbose(1) << "Insertion rejected: Present object is " << (*test.first) << "." << endl; 1087 } 1088 TestSets[mol->AtomCount].insert(mol->end->previous->nr); 1089 TestSets[mol->AtomCount].insert(mol->end->previous->previous->previous->nr); 1090 1091 // constructing Graph structure 1092 cout << "Generating Subgraph class." << endl; 1093 Graph Subgraphs; 1094 1095 // insert KeySets into Subgraphs 1096 cout << "Inserting KeySets into Subgraph class." << endl; 1097 for (int j=0;j<mol->AtomCount;j++) { 1098 Subgraphs.insert(GraphPair (TestSets[j],pair<int, double>(counter++, 1.))); 1099 } 1100 cout << "Testing insertion of already present item in Subgraph." << endl; 1101 GraphTestPair test2; 1102 test2 = Subgraphs.insert(GraphPair (TestSets[mol->AtomCount],pair<int, double>(counter++, 1.))); 1103 if (test2.second) { 1104 cout << Verbose(1) << "Insertion worked?!" << endl; 1105 } else { 1106 cout << Verbose(1) << "Insertion rejected: Present object is " << (*(test2.first)).second.first << "." << endl; 1107 } 1108 1109 // show graphs 1110 cout << "Showing Subgraph's contents, checking that it's sorted." << endl; 1111 Graph::iterator A = Subgraphs.begin(); 1112 while (A != Subgraphs.end()) { 1113 cout << (*A).second.first << ": "; 1114 KeySet::iterator key = (*A).first.begin(); 1115 comp = -1; 1116 while (key != (*A).first.end()) { 1117 if ((*key) > comp) 1118 cout << (*key) << " "; 1119 else 1120 cout << (*key) << "! "; 1121 comp = (*key); 1122 key++; 1123 } 1124 cout << endl; 1125 A++; 1126 } 1127 delete(mol); 1128 1128 }; 1129 1129 … … 1136 1136 static void SaveConfig(char *ConfigFileName, config *configuration, periodentafel *periode, MoleculeListClass *molecules) 1137 1137 { 1138 char filename[MAXSTRINGSIZE];1139 ofstream output;1140 molecule *mol = new molecule(periode);1141 1142 // merge all molecules in MoleculeListClass into this molecule1143 int N = molecules->ListOfMolecules.size();1144 int *src = new int(N);1145 N=0;1146 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)1147 src[N++] = (*ListRunner)->IndexNr;1148 molecules->SimpleMultiAdd(mol, src, N);1149 1150 cout << Verbose(0) << "Storing configuration ... " << endl;1151 // get correct valence orbitals1152 mol->CalculateOrbitals(*configuration);1153 configuration->InitMaxMinStopStep = configuration->MaxMinStopStep = configuration->MaxPsiDouble;1154 strcpy(filename, ConfigFileName);1155 if (ConfigFileName != NULL) { // test the file name1156 output.open(ConfigFileName, ios::trunc);1157 } else if (strlen(configuration->configname) != 0) {1158 strcpy(filename, configuration->configname);1159 output.open(configuration->configname, ios::trunc);1160 } else {1161 strcpy(filename, DEFAULTCONFIG);1162 output.open(DEFAULTCONFIG, ios::trunc);1163 }1164 output.close();1165 output.clear();1166 cout << Verbose(0) << "Saving of config file ";1167 if (configuration->Save(filename, periode, mol))1168 cout << "successful." << endl;1169 else1170 cout << "failed." << endl;1171 1172 // and save to xyz file1173 if (ConfigFileName != NULL) {1174 strcpy(filename, ConfigFileName);1175 strcat(filename, ".xyz");1176 output.open(filename, ios::trunc);1177 }1178 if (output == NULL) {1179 strcpy(filename,"main_pcp_linux");1180 strcat(filename, ".xyz");1181 output.open(filename, ios::trunc);1182 }1183 cout << Verbose(0) << "Saving of XYZ file ";1184 if (mol->MDSteps <= 1) {1185 if (mol->OutputXYZ(&output))1186 cout << "successful." << endl;1187 else1188 cout << "failed." << endl;1189 } else {1190 if (mol->OutputTrajectoriesXYZ(&output))1191 cout << "successful." << endl;1192 else1193 cout << "failed." << endl;1194 }1195 output.close();1196 output.clear();1197 1198 // and save as MPQC configuration1199 if (ConfigFileName != NULL)1200 strcpy(filename, ConfigFileName);1201 if (output == NULL)1202 strcpy(filename,"main_pcp_linux");1203 cout << Verbose(0) << "Saving as mpqc input ";1204 if (configuration->SaveMPQC(filename, mol))1205 cout << "done." << endl;1206 else1207 cout << "failed." << endl;1208 1209 if (!strcmp(configuration->configpath, configuration->GetDefaultPath())) {1210 cerr << "WARNING: config is found under different path then stated in config file::defaultpath!" << endl;1211 }1212 delete(mol);1138 char filename[MAXSTRINGSIZE]; 1139 ofstream output; 1140 molecule *mol = new molecule(periode); 1141 1142 // merge all molecules in MoleculeListClass into this molecule 1143 int N = molecules->ListOfMolecules.size(); 1144 int *src = new int(N); 1145 N=0; 1146 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) 1147 src[N++] = (*ListRunner)->IndexNr; 1148 molecules->SimpleMultiAdd(mol, src, N); 1149 1150 cout << Verbose(0) << "Storing configuration ... " << endl; 1151 // get correct valence orbitals 1152 mol->CalculateOrbitals(*configuration); 1153 configuration->InitMaxMinStopStep = configuration->MaxMinStopStep = configuration->MaxPsiDouble; 1154 strcpy(filename, ConfigFileName); 1155 if (ConfigFileName != NULL) { // test the file name 1156 output.open(ConfigFileName, ios::trunc); 1157 } else if (strlen(configuration->configname) != 0) { 1158 strcpy(filename, configuration->configname); 1159 output.open(configuration->configname, ios::trunc); 1160 } else { 1161 strcpy(filename, DEFAULTCONFIG); 1162 output.open(DEFAULTCONFIG, ios::trunc); 1163 } 1164 output.close(); 1165 output.clear(); 1166 cout << Verbose(0) << "Saving of config file "; 1167 if (configuration->Save(filename, periode, mol)) 1168 cout << "successful." << endl; 1169 else 1170 cout << "failed." << endl; 1171 1172 // and save to xyz file 1173 if (ConfigFileName != NULL) { 1174 strcpy(filename, ConfigFileName); 1175 strcat(filename, ".xyz"); 1176 output.open(filename, ios::trunc); 1177 } 1178 if (output == NULL) { 1179 strcpy(filename,"main_pcp_linux"); 1180 strcat(filename, ".xyz"); 1181 output.open(filename, ios::trunc); 1182 } 1183 cout << Verbose(0) << "Saving of XYZ file "; 1184 if (mol->MDSteps <= 1) { 1185 if (mol->OutputXYZ(&output)) 1186 cout << "successful." << endl; 1187 else 1188 cout << "failed." << endl; 1189 } else { 1190 if (mol->OutputTrajectoriesXYZ(&output)) 1191 cout << "successful." << endl; 1192 else 1193 cout << "failed." << endl; 1194 } 1195 output.close(); 1196 output.clear(); 1197 1198 // and save as MPQC configuration 1199 if (ConfigFileName != NULL) 1200 strcpy(filename, ConfigFileName); 1201 if (output == NULL) 1202 strcpy(filename,"main_pcp_linux"); 1203 cout << Verbose(0) << "Saving as mpqc input "; 1204 if (configuration->SaveMPQC(filename, mol)) 1205 cout << "done." << endl; 1206 else 1207 cout << "failed." << endl; 1208 1209 if (!strcmp(configuration->configpath, configuration->GetDefaultPath())) { 1210 cerr << "WARNING: config is found under different path then stated in config file::defaultpath!" << endl; 1211 } 1212 delete(mol); 1213 1213 }; 1214 1214 … … 1225 1225 static int ParseCommandLineOptions(int argc, char **argv, MoleculeListClass *&molecules, periodentafel *&periode, config& configuration, char *&ConfigFileName, char *&PathToDatabases) 1226 1226 { 1227 Vector x,y,z,n;// coordinates for absolute point in cell volume1228 double *factor; // unit factor if desired1229 ifstream test;1230 ofstream output;1231 string line;1232 atom *first;1233 bool SaveFlag = false;1234 int ExitFlag = 0;1235 int j;1236 double volume = 0.;1237 enum ConfigStatus config_present = absent;1238 clock_t start,end;1239 int argptr;1240 PathToDatabases = LocalPath;1241 1242 // simply create a new molecule, wherein the config file is loaded and the manipulation takes place1243 molecule *mol = new molecule(periode);1244 molecules->insert(mol);1245 1246 if (argc > 1) { // config file specified as option1247 // 1. : Parse options that just set variables or print help1248 argptr = 1;1249 do {1250 if (argv[argptr][0] == '-') {1251 cout << Verbose(0) << "Recognized command line argument: " << argv[argptr][1] << ".\n";1252 argptr++;1253 switch(argv[argptr-1][1]) {1254 case 'h':1255 case 'H':1256 case '?':1257 cout << "MoleCuilder suite" << endl << "==================" << endl << endl;1258 cout << "Usage: " << argv[0] << "[config file] [-{acefpsthH?vfrp}] [further arguments]" << endl;1259 cout << "or simply " << argv[0] << " without arguments for interactive session." << endl;1260 cout << "\t-a Z x1 x2 x3\tAdd new atom of element Z at coordinates (x1,x2,x3)." << endl;1261 cout << "\t-A <source>\tCreate adjacency list from bonds parsed from 'dbond'-style file." <<endl;1262 cout << "\t-b x1 x2 x3\tCenter atoms in domain with given edge lengths of (x1,x2,x3)." << endl;1263 cout << "\t-B <basis>\tSetting basis to store to MPQC config files." << endl;1264 cout << "\t-c x1 x2 x3\tCenter atoms in domain with a minimum distance to boundary of (x1,x2,x3)." << endl;1265 cout << "\t-D <bond distance>\tDepth-First-Search Analysis of the molecule, giving cycles and tree/back edges." << endl;1266 cout << "\t-O\tCenter atoms in origin." << endl;1267 cout << "\t-d x1 x2 x3\tDuplicate cell along each axis by given factor." << endl;1268 cout << "\t-e <file>\tSets the databases path to be parsed (default: ./)." << endl;1269 cout << "\t-E <id> <Z>\tChange atom <id>'s element to <Z>, <id> begins at 0." << endl;1270 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;1271 cout << "\t-h/-H/-?\tGive this help screen." << endl;1272 cout << "\t-m <0/1>\tCalculate (0)/ Align in(1) PAS with greatest EV along z axis." << endl;1273 cout << "\t-n\tFast parsing (i.e. no trajectories are looked for)." << endl;1274 cout << "\t-N <radius> <file>\tGet non-convex-envelope." << endl;1275 cout << "\t-o <out>\tGet volume of the convex envelope (and store to tecplot file)." << endl;1276 cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl;1277 cout << "\t-P <file>\tParse given forces file and append as an MD step to config file via Verlet." << endl;1278 cout << "\t-r\t\tConvert file from an old pcp syntax." << endl;1279 cout << "\t-R\t\tRemove all atoms out of sphere around a given one." << endl;1280 cout << "\t-t x1 x2 x3\tTranslate all atoms by this vector (x1,x2,x3)." << endl;1281 cout << "\t-T <file> Store temperatures from the config file in <file>." << endl;1282 cout << "\t-s x1 x2 x3\tScale all atom coordinates by this vector (x1,x2,x3)." << endl;1283 cout << "\t-u rho\tsuspend in water solution and output necessary cell lengths, average density rho and repetition." << endl;1284 cout << "\t-v/-V\t\tGives version information." << endl;1285 cout << "Note: config files must not begin with '-' !" << endl;1286 delete(mol);1287 delete(periode);1288 return (1);1289 break;1290 case 'v':1291 case 'V':1292 cout << argv[0] << " " << VERSIONSTRING << endl;1293 cout << "Build your own molecule position set." << endl;1294 delete(mol);1295 delete(periode);1296 return (1);1297 break;1298 case 'e':1299 if ((argptr >= argc) || (argv[argptr][0] == '-')) {1300 cerr << "Not enough or invalid arguments for specifying element db: -e <db file>" << endl;1301 } else {1302 cout << "Using " << argv[argptr] << " as elements database." << endl;1303 PathToDatabases = argv[argptr];1304 argptr+=1;1305 }1306 break;1307 case 'n':1308 cout << "I won't parse trajectories." << endl;1309 configuration.FastParsing = true;1310 break;1311 default:// no match? Step on1312 argptr++;1313 break;1314 }1315 } else1316 argptr++;1317 } while (argptr < argc);1318 1319 // 2. Parse the element database1320 if (periode->LoadPeriodentafel(PathToDatabases)) {1321 cout << Verbose(0) << "Element list loaded successfully." << endl;1322 //periode->Output((ofstream *)&cout);1323 } else {1324 cout << Verbose(0) << "Element list loading failed." << endl;1325 return 1;1326 }1327 // 3. Find config file name and parse if possible1328 if (argv[1][0] != '-') {1329 cout << Verbose(0) << "Config file given." << endl;1330 test.open(argv[1], ios::in);1331 if (test == NULL) {1332 //return (1);1333 output.open(argv[1], ios::out);1334 if (output == NULL) {1335 cout << Verbose(1) << "Specified config file " << argv[1] << " not found." << endl;1336 config_present = absent;1337 } else {1338 cout << "Empty configuration file." << endl;1339 ConfigFileName = argv[1];1340 config_present = empty;1341 output.close();1342 }1343 } else {1344 test.close();1345 ConfigFileName = argv[1];1346 cout << Verbose(1) << "Specified config file found, parsing ... ";1347 switch (configuration.TestSyntax(ConfigFileName, periode, mol)) {1348 case 1:1349 cout << "new syntax." << endl;1350 configuration.Load(ConfigFileName, periode, mol);1351 config_present = present;1352 break;1353 case 0:1354 cout << "old syntax." << endl;1355 configuration.LoadOld(ConfigFileName, periode, mol);1356 config_present = present;1357 break;1358 default:1359 cout << "Unknown syntax or empty, yet present file." << endl;1360 config_present = empty;1361 }1362 }1363 } else1364 config_present = absent;1365 // 4. parse again through options, now for those depending on elements db and config presence1366 argptr = 1;1367 do {1368 cout << "Current Command line argument: " << argv[argptr] << "." << endl;1369 if (argv[argptr][0] == '-') {1370 argptr++;1371 if ((config_present == present) || (config_present == empty)) {1372 switch(argv[argptr-1][1]) {1373 case 'p':1374 ExitFlag = 1;1375 if ((argptr >= argc) || (argv[argptr][0] == '-')) {1376 ExitFlag = 255;1377 cerr << "Not enough arguments for parsing: -p <xyz file>" << endl;1378 } else {1379 SaveFlag = true;1380 cout << Verbose(1) << "Parsing xyz file for new atoms." << endl;1381 if (!mol->AddXYZFile(argv[argptr]))1382 cout << Verbose(2) << "File not found." << endl;1383 else {1384 cout << Verbose(2) << "File found and parsed." << endl;1385 config_present = present;1386 }1387 }1388 break;1389 case 'a':1390 ExitFlag = 1;1391 if ((argptr >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr+1]))) {1392 ExitFlag = 255;1393 cerr << "Not enough or invalid arguments for adding atom: -a <element> <x> <y> <z>" << endl;1394 } else {1395 SaveFlag = true;1396 cout << Verbose(1) << "Adding new atom with element " << argv[argptr] << " at (" << argv[argptr+1] << "," << argv[argptr+2] << "," << argv[argptr+3] << "), ";1397 first = new atom;1398 first->type = periode->FindElement(atoi(argv[argptr]));1399 if (first->type != NULL)1400 cout << Verbose(2) << "found element " << first->type->name << endl;1401 for (int i=NDIM;i--;)1402 first->x.x[i] = atof(argv[argptr+1+i]);1403 if (first->type != NULL) {1404 mol->AddAtom(first);// add to molecule1405 if ((config_present == empty) && (mol->AtomCount != 0))1406 config_present = present;1407 } else1408 cerr << Verbose(1) << "Could not find the specified element." << endl;1409 argptr+=4;1410 }1411 break;1412 default:// no match? Don't step on (this is done in next switch's default)1413 break;1414 }1415 }1416 if (config_present == present) {1417 switch(argv[argptr-1][1]) {1418 case 'B':1419 if ((argptr >= argc) || (argv[argptr][0] == '-')) {1420 ExitFlag = 255;1421 cerr << "Not enough or invalid arguments given for setting MPQC basis: -B <basis name>" << endl;1422 } else {1423 configuration.basis = argv[argptr];1424 cout << Verbose(1) << "Setting MPQC basis to " << configuration.basis << "." << endl;1425 argptr+=1;1426 }1427 break;1428 case 'D':1429 ExitFlag = 1;1430 {1431 cout << Verbose(1) << "Depth-First-Search Analysis." << endl;1432 MoleculeLeafClass *Subgraphs = NULL;// list of subgraphs from DFS analysis1433 int *MinimumRingSize = new int[mol->AtomCount];1434 atom ***ListOfLocalAtoms = NULL;1435 int FragmentCounter = 0;1436 class StackClass<bond *> *BackEdgeStack = NULL;1437 class StackClass<bond *> *LocalBackEdgeStack = NULL;1438 mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr]), configuration.GetIsAngstroem());1439 mol->CreateListOfBondsPerAtom((ofstream *)&cout);1440 Subgraphs = mol->DepthFirstSearchAnalysis((ofstream *)&cout, BackEdgeStack);1441 if (Subgraphs != NULL) {1442 Subgraphs->next->FillBondStructureFromReference((ofstream *)&cout, mol, (FragmentCounter = 0), ListOfLocalAtoms, false);// we want to keep the created ListOfLocalAtoms1443 while (Subgraphs->next != NULL) {1444 Subgraphs = Subgraphs->next;1445 LocalBackEdgeStack = new StackClass<bond *> (Subgraphs->Leaf->BondCount);1446 Subgraphs->Leaf->PickLocalBackEdges((ofstream *)&cout, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack);1447 Subgraphs->Leaf->CyclicStructureAnalysis((ofstream *)&cout, BackEdgeStack, MinimumRingSize);1448 delete(LocalBackEdgeStack);1449 delete(Subgraphs->previous);1450 }1451 delete(Subgraphs);1452 for (int i=0;i<FragmentCounter;i++)1453 Free((void **)&ListOfLocalAtoms[FragmentCounter], "ParseCommandLineOptions: **ListOfLocalAtoms[]");1454 Free((void **)&ListOfLocalAtoms, "ParseCommandLineOptions: ***ListOfLocalAtoms");1455 }1456 delete(BackEdgeStack);1457 delete[](MinimumRingSize);1458 }1459 //argptr+=1;1460 break;1461 case 'E':1462 ExitFlag = 1;1463 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (argv[argptr+1][0] == '-')) {1464 ExitFlag = 255;1465 cerr << "Not enough or invalid arguments given for changing element: -E <atom nr.> <element>" << endl;1466 } else {1467 SaveFlag = true;1468 cout << Verbose(1) << "Changing atom " << argv[argptr] << " to element " << argv[argptr+1] << "." << endl;1469 first = mol->FindAtom(atoi(argv[argptr]));1470 first->type = periode->FindElement(atoi(argv[argptr+1]));1471 argptr+=2;1472 }1473 break;1474 case 'A':1475 ExitFlag = 1;1476 if ((argptr >= argc) || (argv[argptr][0] == '-')) {1477 ExitFlag =255;1478 cerr << "Missing source file for bonds in molecule: -A <bond sourcefile>" << endl;1479 } else {1480 cout << "Parsing bonds from " << argv[argptr] << "." << endl;1481 ifstream *input = new ifstream(argv[argptr]);1482 mol->CreateAdjacencyList2((ofstream *)&cout, input);1483 input->close();1484 argptr+=1;1485 }1486 break;1487 case 'N':1488 ExitFlag = 1;1489 if ((argptr+1 >= argc) || (argv[argptr+1][0] == '-')){1490 ExitFlag = 255;1491 cerr << "Not enough or invalid arguments given for non-convex envelope: -o <radius> <tecplot output file>" << endl;1492 } else {1493 class Tesselation T;1494 int N = 15;1495 int number = 100;1496 string filename(argv[argptr+1]);1497 filename.append(".csv");1498 cout << Verbose(0) << "Evaluating non-convex envelope.";1499 cout << Verbose(1) << "Using rolling ball of radius " << atof(argv[argptr]) << " and storing tecplot data in " << argv[argptr+1] << "." << endl;1500 LinkedCell LCList(mol, atof(argv[argptr]));// \NOTE not twice the radius??1501 Find_non_convex_border((ofstream *)&cout, mol, &T, &LCList, argv[argptr+1], atof(argv[argptr]));1502 //FindDistributionOfEllipsoids((ofstream *)&cout, &T, &LCList, N, number, filename.c_str());1503 argptr+=2;1504 }1505 break;1506 case 'T':1507 ExitFlag = 1;1508 if ((argptr >= argc) || (argv[argptr][0] == '-')) {1509 ExitFlag = 255;1510 cerr << "Not enough or invalid arguments given for storing tempature: -T <temperature file>" << endl;1511 } else {1512 cout << Verbose(1) << "Storing temperatures in " << argv[argptr] << "." << endl;1513 ofstream *output = new ofstream(argv[argptr], ios::trunc);1514 if (!mol->OutputTemperatureFromTrajectories((ofstream *)&cout, 0, mol->MDSteps, output))1515 cout << Verbose(2) << "File could not be written." << endl;1516 else1517 cout << Verbose(2) << "File stored." << endl;1518 output->close();1519 delete(output);1520 argptr+=1;1521 }1522 break;1523 case 'P':1524 ExitFlag = 1;1525 if ((argptr >= argc) || (argv[argptr][0] == '-')) {1526 ExitFlag = 255;1527 cerr << "Not enough or invalid arguments given for parsing and integrating forces: -P <forces file>" << endl;1528 } else {1529 SaveFlag = true;1530 cout << Verbose(1) << "Parsing forces file and Verlet integrating." << endl;1531 if (!mol->VerletForceIntegration(argv[argptr], configuration.Deltat, configuration.GetIsAngstroem()))1532 cout << Verbose(2) << "File not found." << endl;1533 else1534 cout << Verbose(2) << "File found and parsed." << endl;1535 argptr+=1;1536 }1537 break;1227 Vector x,y,z,n; // coordinates for absolute point in cell volume 1228 double *factor; // unit factor if desired 1229 ifstream test; 1230 ofstream output; 1231 string line; 1232 atom *first; 1233 bool SaveFlag = false; 1234 int ExitFlag = 0; 1235 int j; 1236 double volume = 0.; 1237 enum ConfigStatus config_present = absent; 1238 clock_t start,end; 1239 int argptr; 1240 PathToDatabases = LocalPath; 1241 1242 // simply create a new molecule, wherein the config file is loaded and the manipulation takes place 1243 molecule *mol = new molecule(periode); 1244 molecules->insert(mol); 1245 1246 if (argc > 1) { // config file specified as option 1247 // 1. : Parse options that just set variables or print help 1248 argptr = 1; 1249 do { 1250 if (argv[argptr][0] == '-') { 1251 cout << Verbose(0) << "Recognized command line argument: " << argv[argptr][1] << ".\n"; 1252 argptr++; 1253 switch(argv[argptr-1][1]) { 1254 case 'h': 1255 case 'H': 1256 case '?': 1257 cout << "MoleCuilder suite" << endl << "==================" << endl << endl; 1258 cout << "Usage: " << argv[0] << "[config file] [-{acefpsthH?vfrp}] [further arguments]" << endl; 1259 cout << "or simply " << argv[0] << " without arguments for interactive session." << endl; 1260 cout << "\t-a Z x1 x2 x3\tAdd new atom of element Z at coordinates (x1,x2,x3)." << endl; 1261 cout << "\t-A <source>\tCreate adjacency list from bonds parsed from 'dbond'-style file." <<endl; 1262 cout << "\t-b x1 x2 x3\tCenter atoms in domain with given edge lengths of (x1,x2,x3)." << endl; 1263 cout << "\t-B <basis>\tSetting basis to store to MPQC config files." << endl; 1264 cout << "\t-c x1 x2 x3\tCenter atoms in domain with a minimum distance to boundary of (x1,x2,x3)." << endl; 1265 cout << "\t-D <bond distance>\tDepth-First-Search Analysis of the molecule, giving cycles and tree/back edges." << endl; 1266 cout << "\t-O\tCenter atoms in origin." << endl; 1267 cout << "\t-d x1 x2 x3\tDuplicate cell along each axis by given factor." << endl; 1268 cout << "\t-e <file>\tSets the databases path to be parsed (default: ./)." << endl; 1269 cout << "\t-E <id> <Z>\tChange atom <id>'s element to <Z>, <id> begins at 0." << endl; 1270 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; 1271 cout << "\t-h/-H/-?\tGive this help screen." << endl; 1272 cout << "\t-m <0/1>\tCalculate (0)/ Align in(1) PAS with greatest EV along z axis." << endl; 1273 cout << "\t-n\tFast parsing (i.e. no trajectories are looked for)." << endl; 1274 cout << "\t-N <radius> <file>\tGet non-convex-envelope." << endl; 1275 cout << "\t-o <out>\tGet volume of the convex envelope (and store to tecplot file)." << endl; 1276 cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl; 1277 cout << "\t-P <file>\tParse given forces file and append as an MD step to config file via Verlet." << endl; 1278 cout << "\t-r\t\tConvert file from an old pcp syntax." << endl; 1279 cout << "\t-R\t\tRemove all atoms out of sphere around a given one." << endl; 1280 cout << "\t-t x1 x2 x3\tTranslate all atoms by this vector (x1,x2,x3)." << endl; 1281 cout << "\t-T <file> Store temperatures from the config file in <file>." << endl; 1282 cout << "\t-s x1 x2 x3\tScale all atom coordinates by this vector (x1,x2,x3)." << endl; 1283 cout << "\t-u rho\tsuspend in water solution and output necessary cell lengths, average density rho and repetition." << endl; 1284 cout << "\t-v/-V\t\tGives version information." << endl; 1285 cout << "Note: config files must not begin with '-' !" << endl; 1286 delete(mol); 1287 delete(periode); 1288 return (1); 1289 break; 1290 case 'v': 1291 case 'V': 1292 cout << argv[0] << " " << VERSIONSTRING << endl; 1293 cout << "Build your own molecule position set." << endl; 1294 delete(mol); 1295 delete(periode); 1296 return (1); 1297 break; 1298 case 'e': 1299 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1300 cerr << "Not enough or invalid arguments for specifying element db: -e <db file>" << endl; 1301 } else { 1302 cout << "Using " << argv[argptr] << " as elements database." << endl; 1303 PathToDatabases = argv[argptr]; 1304 argptr+=1; 1305 } 1306 break; 1307 case 'n': 1308 cout << "I won't parse trajectories." << endl; 1309 configuration.FastParsing = true; 1310 break; 1311 default: // no match? Step on 1312 argptr++; 1313 break; 1314 } 1315 } else 1316 argptr++; 1317 } while (argptr < argc); 1318 1319 // 2. Parse the element database 1320 if (periode->LoadPeriodentafel(PathToDatabases)) { 1321 cout << Verbose(0) << "Element list loaded successfully." << endl; 1322 //periode->Output((ofstream *)&cout); 1323 } else { 1324 cout << Verbose(0) << "Element list loading failed." << endl; 1325 return 1; 1326 } 1327 // 3. Find config file name and parse if possible 1328 if (argv[1][0] != '-') { 1329 cout << Verbose(0) << "Config file given." << endl; 1330 test.open(argv[1], ios::in); 1331 if (test == NULL) { 1332 //return (1); 1333 output.open(argv[1], ios::out); 1334 if (output == NULL) { 1335 cout << Verbose(1) << "Specified config file " << argv[1] << " not found." << endl; 1336 config_present = absent; 1337 } else { 1338 cout << "Empty configuration file." << endl; 1339 ConfigFileName = argv[1]; 1340 config_present = empty; 1341 output.close(); 1342 } 1343 } else { 1344 test.close(); 1345 ConfigFileName = argv[1]; 1346 cout << Verbose(1) << "Specified config file found, parsing ... "; 1347 switch (configuration.TestSyntax(ConfigFileName, periode, mol)) { 1348 case 1: 1349 cout << "new syntax." << endl; 1350 configuration.Load(ConfigFileName, periode, mol); 1351 config_present = present; 1352 break; 1353 case 0: 1354 cout << "old syntax." << endl; 1355 configuration.LoadOld(ConfigFileName, periode, mol); 1356 config_present = present; 1357 break; 1358 default: 1359 cout << "Unknown syntax or empty, yet present file." << endl; 1360 config_present = empty; 1361 } 1362 } 1363 } else 1364 config_present = absent; 1365 // 4. parse again through options, now for those depending on elements db and config presence 1366 argptr = 1; 1367 do { 1368 cout << "Current Command line argument: " << argv[argptr] << "." << endl; 1369 if (argv[argptr][0] == '-') { 1370 argptr++; 1371 if ((config_present == present) || (config_present == empty)) { 1372 switch(argv[argptr-1][1]) { 1373 case 'p': 1374 ExitFlag = 1; 1375 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1376 ExitFlag = 255; 1377 cerr << "Not enough arguments for parsing: -p <xyz file>" << endl; 1378 } else { 1379 SaveFlag = true; 1380 cout << Verbose(1) << "Parsing xyz file for new atoms." << endl; 1381 if (!mol->AddXYZFile(argv[argptr])) 1382 cout << Verbose(2) << "File not found." << endl; 1383 else { 1384 cout << Verbose(2) << "File found and parsed." << endl; 1385 config_present = present; 1386 } 1387 } 1388 break; 1389 case 'a': 1390 ExitFlag = 1; 1391 if ((argptr >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr+1]))) { 1392 ExitFlag = 255; 1393 cerr << "Not enough or invalid arguments for adding atom: -a <element> <x> <y> <z>" << endl; 1394 } else { 1395 SaveFlag = true; 1396 cout << Verbose(1) << "Adding new atom with element " << argv[argptr] << " at (" << argv[argptr+1] << "," << argv[argptr+2] << "," << argv[argptr+3] << "), "; 1397 first = new atom; 1398 first->type = periode->FindElement(atoi(argv[argptr])); 1399 if (first->type != NULL) 1400 cout << Verbose(2) << "found element " << first->type->name << endl; 1401 for (int i=NDIM;i--;) 1402 first->x.x[i] = atof(argv[argptr+1+i]); 1403 if (first->type != NULL) { 1404 mol->AddAtom(first); // add to molecule 1405 if ((config_present == empty) && (mol->AtomCount != 0)) 1406 config_present = present; 1407 } else 1408 cerr << Verbose(1) << "Could not find the specified element." << endl; 1409 argptr+=4; 1410 } 1411 break; 1412 default: // no match? Don't step on (this is done in next switch's default) 1413 break; 1414 } 1415 } 1416 if (config_present == present) { 1417 switch(argv[argptr-1][1]) { 1418 case 'B': 1419 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1420 ExitFlag = 255; 1421 cerr << "Not enough or invalid arguments given for setting MPQC basis: -B <basis name>" << endl; 1422 } else { 1423 configuration.basis = argv[argptr]; 1424 cout << Verbose(1) << "Setting MPQC basis to " << configuration.basis << "." << endl; 1425 argptr+=1; 1426 } 1427 break; 1428 case 'D': 1429 ExitFlag = 1; 1430 { 1431 cout << Verbose(1) << "Depth-First-Search Analysis." << endl; 1432 MoleculeLeafClass *Subgraphs = NULL; // list of subgraphs from DFS analysis 1433 int *MinimumRingSize = new int[mol->AtomCount]; 1434 atom ***ListOfLocalAtoms = NULL; 1435 int FragmentCounter = 0; 1436 class StackClass<bond *> *BackEdgeStack = NULL; 1437 class StackClass<bond *> *LocalBackEdgeStack = NULL; 1438 mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr]), configuration.GetIsAngstroem()); 1439 mol->CreateListOfBondsPerAtom((ofstream *)&cout); 1440 Subgraphs = mol->DepthFirstSearchAnalysis((ofstream *)&cout, BackEdgeStack); 1441 if (Subgraphs != NULL) { 1442 Subgraphs->next->FillBondStructureFromReference((ofstream *)&cout, mol, (FragmentCounter = 0), ListOfLocalAtoms, false); // we want to keep the created ListOfLocalAtoms 1443 while (Subgraphs->next != NULL) { 1444 Subgraphs = Subgraphs->next; 1445 LocalBackEdgeStack = new StackClass<bond *> (Subgraphs->Leaf->BondCount); 1446 Subgraphs->Leaf->PickLocalBackEdges((ofstream *)&cout, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack); 1447 Subgraphs->Leaf->CyclicStructureAnalysis((ofstream *)&cout, BackEdgeStack, MinimumRingSize); 1448 delete(LocalBackEdgeStack); 1449 delete(Subgraphs->previous); 1450 } 1451 delete(Subgraphs); 1452 for (int i=0;i<FragmentCounter;i++) 1453 Free((void **)&ListOfLocalAtoms[FragmentCounter], "ParseCommandLineOptions: **ListOfLocalAtoms[]"); 1454 Free((void **)&ListOfLocalAtoms, "ParseCommandLineOptions: ***ListOfLocalAtoms"); 1455 } 1456 delete(BackEdgeStack); 1457 delete[](MinimumRingSize); 1458 } 1459 //argptr+=1; 1460 break; 1461 case 'E': 1462 ExitFlag = 1; 1463 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (argv[argptr+1][0] == '-')) { 1464 ExitFlag = 255; 1465 cerr << "Not enough or invalid arguments given for changing element: -E <atom nr.> <element>" << endl; 1466 } else { 1467 SaveFlag = true; 1468 cout << Verbose(1) << "Changing atom " << argv[argptr] << " to element " << argv[argptr+1] << "." << endl; 1469 first = mol->FindAtom(atoi(argv[argptr])); 1470 first->type = periode->FindElement(atoi(argv[argptr+1])); 1471 argptr+=2; 1472 } 1473 break; 1474 case 'A': 1475 ExitFlag = 1; 1476 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1477 ExitFlag =255; 1478 cerr << "Missing source file for bonds in molecule: -A <bond sourcefile>" << endl; 1479 } else { 1480 cout << "Parsing bonds from " << argv[argptr] << "." << endl; 1481 ifstream *input = new ifstream(argv[argptr]); 1482 mol->CreateAdjacencyList2((ofstream *)&cout, input); 1483 input->close(); 1484 argptr+=1; 1485 } 1486 break; 1487 case 'N': 1488 ExitFlag = 1; 1489 if ((argptr+1 >= argc) || (argv[argptr+1][0] == '-')){ 1490 ExitFlag = 255; 1491 cerr << "Not enough or invalid arguments given for non-convex envelope: -o <radius> <tecplot output file>" << endl; 1492 } else { 1493 class Tesselation T; 1494 int N = 15; 1495 int number = 100; 1496 string filename(argv[argptr+1]); 1497 filename.append(".csv"); 1498 cout << Verbose(0) << "Evaluating non-convex envelope."; 1499 cout << Verbose(1) << "Using rolling ball of radius " << atof(argv[argptr]) << " and storing tecplot data in " << argv[argptr+1] << "." << endl; 1500 LinkedCell LCList(mol, atof(argv[argptr])); // \NOTE not twice the radius?? 1501 Find_non_convex_border((ofstream *)&cout, mol, &T, &LCList, argv[argptr+1], atof(argv[argptr])); 1502 //FindDistributionOfEllipsoids((ofstream *)&cout, &T, &LCList, N, number, filename.c_str()); 1503 argptr+=2; 1504 } 1505 break; 1506 case 'T': 1507 ExitFlag = 1; 1508 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1509 ExitFlag = 255; 1510 cerr << "Not enough or invalid arguments given for storing tempature: -T <temperature file>" << endl; 1511 } else { 1512 cout << Verbose(1) << "Storing temperatures in " << argv[argptr] << "." << endl; 1513 ofstream *output = new ofstream(argv[argptr], ios::trunc); 1514 if (!mol->OutputTemperatureFromTrajectories((ofstream *)&cout, 0, mol->MDSteps, output)) 1515 cout << Verbose(2) << "File could not be written." << endl; 1516 else 1517 cout << Verbose(2) << "File stored." << endl; 1518 output->close(); 1519 delete(output); 1520 argptr+=1; 1521 } 1522 break; 1523 case 'P': 1524 ExitFlag = 1; 1525 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1526 ExitFlag = 255; 1527 cerr << "Not enough or invalid arguments given for parsing and integrating forces: -P <forces file>" << endl; 1528 } else { 1529 SaveFlag = true; 1530 cout << Verbose(1) << "Parsing forces file and Verlet integrating." << endl; 1531 if (!mol->VerletForceIntegration(argv[argptr], configuration.Deltat, configuration.GetIsAngstroem())) 1532 cout << Verbose(2) << "File not found." << endl; 1533 else 1534 cout << Verbose(2) << "File found and parsed." << endl; 1535 argptr+=1; 1536 } 1537 break; 1538 1538 case 'R': 1539 1539 ExitFlag = 1; … … 1561 1561 } 1562 1562 break; 1563 case 't':1564 ExitFlag = 1;1565 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {1566 ExitFlag = 255;1567 cerr << "Not enough or invalid arguments given for translation: -t <x> <y> <z>" << endl;1568 } else {1569 ExitFlag = 1;1570 SaveFlag = true;1571 cout << Verbose(1) << "Translating all ions to new origin." << endl;1572 for (int i=NDIM;i--;)1573 x.x[i] = atof(argv[argptr+i]);1574 mol->Translate((const Vector *)&x);1575 argptr+=3;1576 }1577 break;1578 case 's':1579 ExitFlag = 1;1580 if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) {1581 ExitFlag = 255;1582 cerr << "Not enough or invalid arguments given for scaling: -s <factor/[factor_x]> [factor_y] [factor_z]" << endl;1583 } else {1584 SaveFlag = true;1585 j = -1;1586 cout << Verbose(1) << "Scaling all ion positions by factor." << endl;1587 factor = new double[NDIM];1588 factor[0] = atof(argv[argptr]);1589 if ((argptr < argc) && (IsValidNumber(argv[argptr])))1590 argptr++;1591 factor[1] = atof(argv[argptr]);1592 if ((argptr < argc) && (IsValidNumber(argv[argptr])))1593 argptr++;1594 factor[2] = atof(argv[argptr]);1595 mol->Scale(&factor);1596 for (int i=0;i<NDIM;i++) {1597 j += i+1;1598 x.x[i] = atof(argv[NDIM+i]);1599 mol->cell_size[j]*=factor[i];1600 }1601 delete[](factor);1602 argptr+=1;1603 }1604 break;1605 case 'b':1606 ExitFlag = 1;1607 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {1608 ExitFlag = 255;1609 cerr << "Not enough or invalid arguments given for centering in box: -b <length_x> <length_y> <length_z>" << endl;1610 } else {1611 SaveFlag = true;1612 j = -1;1613 cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl;1614 j=-1;1615 for (int i=0;i<NDIM;i++) {1616 j += i+1;1617 x.x[i] = atof(argv[argptr++]);1618 mol->cell_size[j] += x.x[i]*2.;1619 }1620 // center1621 mol->CenterInBox((ofstream *)&cout, &x);1622 // update Box of atoms by boundary1623 mol->SetBoxDimension(&x);1624 }1625 break;1626 case 'c':1627 ExitFlag = 1;1628 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {1629 ExitFlag = 255;1630 cerr << "Not enough or invalid arguments given for centering with boundary: -c <boundary_x> <boundary_y> <boundary_z>" << endl;1631 } else {1632 SaveFlag = true;1633 j = -1;1634 cout << Verbose(1) << "Centering atoms in config file within given additional boundary." << endl;1635 // make every coordinate positive1636 mol->CenterEdge((ofstream *)&cout, &x);1637 // update Box of atoms by boundary1638 mol->SetBoxDimension(&x);1639 // translate each coordinate by boundary1640 j=-1;1641 for (int i=0;i<NDIM;i++) {1642 j += i+1;1643 x.x[i] = atof(argv[argptr++]);1644 mol->cell_size[j] += x.x[i]*2.;1645 }1646 mol->Translate((const Vector *)&x);1647 }1648 break;1649 case 'O':1650 ExitFlag = 1;1651 SaveFlag = true;1652 cout << Verbose(1) << "Centering atoms in origin." << endl;1653 mol->CenterOrigin((ofstream *)&cout, &x);1654 mol->SetBoxDimension(&x);1655 break;1656 case 'r':1657 ExitFlag = 1;1658 SaveFlag = true;1659 cout << Verbose(1) << "Converting config file from supposed old to new syntax." << endl;1660 break;1661 case 'F':1662 case 'f':1663 ExitFlag = 1;1664 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1]))) {1665 ExitFlag = 255;1666 cerr << "Not enough or invalid arguments for fragmentation: -f <max. bond distance> <bond order>" << endl;1667 } else {1668 cout << "Fragmenting molecule with bond distance " << argv[argptr] << " angstroem, order of " << argv[argptr+1] << "." << endl;1669 cout << Verbose(0) << "Creating connection matrix..." << endl;1670 start = clock();1671 mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr++]), configuration.GetIsAngstroem());1672 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl;1673 if (mol->first->next != mol->last) {1674 ExitFlag = mol->FragmentMolecule((ofstream *)&cout, atoi(argv[argptr]), &configuration);1675 }1676 end = clock();1677 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;1678 argptr+=2;1679 }1680 break;1681 case 'm':1682 ExitFlag = 1;1683 j = atoi(argv[argptr++]);1684 if ((j<0) || (j>1)) {1685 cerr << Verbose(1) << "ERROR: Argument of '-m' should be either 0 for no-rotate or 1 for rotate." << endl;1686 j = 0;1687 }1688 if (j) {1689 SaveFlag = true;1690 cout << Verbose(0) << "Converting to prinicipal axis system." << endl;1691 } else1692 cout << Verbose(0) << "Evaluating prinicipal axis." << endl;1693 mol->PrincipalAxisSystem((ofstream *)&cout, (bool)j);1694 break;1695 case 'o':1696 ExitFlag = 1;1697 if ((argptr >= argc) || (argv[argptr][0] == '-')){1698 ExitFlag = 255;1699 cerr << "Not enough or invalid arguments given for convex envelope: -o <tecplot output file>" << endl;1700 } else {1701 cout << Verbose(0) << "Evaluating volume of the convex envelope.";1702 cout << Verbose(1) << "Storing tecplot data in " << argv[argptr] << "." << endl;1703 VolumeOfConvexEnvelope((ofstream *)&cout, argv[argptr], &configuration, NULL, mol);1704 argptr+=1;1705 }1706 break;1707 case 'U':1708 ExitFlag = 1;1709 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) ) {1710 ExitFlag = 255;1711 cerr << "Not enough or invalid arguments given for suspension with specified volume: -U <volume> <density>" << endl;1712 volume = -1; // for case 'u': don't print error again1713 } else {1714 volume = atof(argv[argptr++]);1715 cout << Verbose(0) << "Using " << volume << " angstrom^3 as the volume instead of convex envelope one's." << endl;1716 }1717 case 'u':1718 ExitFlag = 1;1719 if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) {1720 if (volume != -1)1721 ExitFlag = 255;1722 cerr << "Not enough arguments given for suspension: -u <density>" << endl;1723 } else {1724 double density;1725 SaveFlag = true;1726 cout << Verbose(0) << "Evaluating necessary cell volume for a cluster suspended in water.";1727 density = atof(argv[argptr++]);1728 if (density < 1.0) {1729 cerr << Verbose(0) << "Density must be greater than 1.0g/cm^3 !" << endl;1730 density = 1.3;1731 }1732 // for(int i=0;i<NDIM;i++) {1733 // repetition[i] = atoi(argv[argptr++]);1734 // if (repetition[i] < 1)1735 // cerr << Verbose(0) << "ERROR: repetition value must be greater 1!" << endl;1736 // repetition[i] = 1;1737 // }1738 PrepareClustersinWater((ofstream *)&cout, &configuration, mol, volume, density);// if volume == 0, will calculate from ConvexEnvelope1739 }1740 break;1741 case 'd':1742 ExitFlag = 1;1743 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {1744 ExitFlag = 255;1745 cerr << "Not enough or invalid arguments given for repeating cells: -d <repeat_x> <repeat_y> <repeat_z>" << endl;1746 } else {1747 SaveFlag = true;1748 for (int axis = 1; axis <= NDIM; axis++) {1749 int faktor = atoi(argv[argptr++]);1750 int count;1751 element ** Elements;1752 Vector ** vectors;1753 if (faktor < 1) {1754 cerr << Verbose(0) << "ERROR: Repetition faktor mus be greater than 1!" << endl;1755 faktor = 1;1756 }1757 mol->CountAtoms((ofstream *)&cout);// recount atoms1758 if (mol->AtomCount != 0) {// if there is more than none1759 count = mol->AtomCount;// is changed becausing of adding, thus has to be stored away beforehand1760 Elements = new element *[count];1761 vectors = new Vector *[count];1762 j = 0;1763 first = mol->start;1764 while (first->next != mol->end) {// make a list of all atoms with coordinates and element1765 first = first->next;1766 Elements[j] = first->type;1767 vectors[j] = &first->x;1768 j++;1769 }1770 if (count != j)1771 cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl;1772 x.Zero();1773 y.Zero();1774 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 magnitude1775 for (int i=1;i<faktor;i++) {// then add this list with respective translation factor times1776 x.AddVector(&y); // per factor one cell width further1777 for (int k=count;k--;) { // go through every atom of the original cell1778 first = new atom(); // create a new body1779 first->x.CopyVector(vectors[k]);// use coordinate of original atom1780 first->x.AddVector(&x);// translate the coordinates1781 first->type = Elements[k];// insert original element1782 mol->AddAtom(first);// and add to the molecule (which increments ElementsInMolecule, AtomCount, ...)1783 }1784 }1785 // free memory1786 delete[](Elements);1787 delete[](vectors);1788 // correct cell size1789 if (axis < 0) { // if sign was negative, we have to translate everything1790 x.Zero();1791 x.AddVector(&y);1792 x.Scale(-(faktor-1));1793 mol->Translate(&x);1794 }1795 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor;1796 }1797 }1798 }1799 break;1800 default:// no match? Step on1801 if ((argptr < argc) && (argv[argptr][0] != '-')) // if it started with a '-' we've already made a step!1802 argptr++;1803 break;1804 }1805 }1806 } else argptr++;1807 } while (argptr < argc);1808 if (SaveFlag)1809 SaveConfig(ConfigFileName, &configuration, periode, molecules);1810 if ((ExitFlag >= 1)) {1811 delete(mol);1812 delete(periode);1813 return (ExitFlag);1814 }1815 } else {// no arguments, hence scan the elements db1816 if (periode->LoadPeriodentafel(PathToDatabases))1817 cout << Verbose(0) << "Element list loaded successfully." << endl;1818 else1819 cout << Verbose(0) << "Element list loading failed." << endl;1820 configuration.RetrieveConfigPathAndName("main_pcp_linux");1821 }1822 return(0);1563 case 't': 1564 ExitFlag = 1; 1565 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) { 1566 ExitFlag = 255; 1567 cerr << "Not enough or invalid arguments given for translation: -t <x> <y> <z>" << endl; 1568 } else { 1569 ExitFlag = 1; 1570 SaveFlag = true; 1571 cout << Verbose(1) << "Translating all ions to new origin." << endl; 1572 for (int i=NDIM;i--;) 1573 x.x[i] = atof(argv[argptr+i]); 1574 mol->Translate((const Vector *)&x); 1575 argptr+=3; 1576 } 1577 break; 1578 case 's': 1579 ExitFlag = 1; 1580 if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) { 1581 ExitFlag = 255; 1582 cerr << "Not enough or invalid arguments given for scaling: -s <factor/[factor_x]> [factor_y] [factor_z]" << endl; 1583 } else { 1584 SaveFlag = true; 1585 j = -1; 1586 cout << Verbose(1) << "Scaling all ion positions by factor." << endl; 1587 factor = new double[NDIM]; 1588 factor[0] = atof(argv[argptr]); 1589 if ((argptr < argc) && (IsValidNumber(argv[argptr]))) 1590 argptr++; 1591 factor[1] = atof(argv[argptr]); 1592 if ((argptr < argc) && (IsValidNumber(argv[argptr]))) 1593 argptr++; 1594 factor[2] = atof(argv[argptr]); 1595 mol->Scale(&factor); 1596 for (int i=0;i<NDIM;i++) { 1597 j += i+1; 1598 x.x[i] = atof(argv[NDIM+i]); 1599 mol->cell_size[j]*=factor[i]; 1600 } 1601 delete[](factor); 1602 argptr+=1; 1603 } 1604 break; 1605 case 'b': 1606 ExitFlag = 1; 1607 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) { 1608 ExitFlag = 255; 1609 cerr << "Not enough or invalid arguments given for centering in box: -b <length_x> <length_y> <length_z>" << endl; 1610 } else { 1611 SaveFlag = true; 1612 j = -1; 1613 cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl; 1614 j=-1; 1615 for (int i=0;i<NDIM;i++) { 1616 j += i+1; 1617 x.x[i] = atof(argv[argptr++]); 1618 mol->cell_size[j] += x.x[i]*2.; 1619 } 1620 // center 1621 mol->CenterInBox((ofstream *)&cout, &x); 1622 // update Box of atoms by boundary 1623 mol->SetBoxDimension(&x); 1624 } 1625 break; 1626 case 'c': 1627 ExitFlag = 1; 1628 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) { 1629 ExitFlag = 255; 1630 cerr << "Not enough or invalid arguments given for centering with boundary: -c <boundary_x> <boundary_y> <boundary_z>" << endl; 1631 } else { 1632 SaveFlag = true; 1633 j = -1; 1634 cout << Verbose(1) << "Centering atoms in config file within given additional boundary." << endl; 1635 // make every coordinate positive 1636 mol->CenterEdge((ofstream *)&cout, &x); 1637 // update Box of atoms by boundary 1638 mol->SetBoxDimension(&x); 1639 // translate each coordinate by boundary 1640 j=-1; 1641 for (int i=0;i<NDIM;i++) { 1642 j += i+1; 1643 x.x[i] = atof(argv[argptr++]); 1644 mol->cell_size[j] += x.x[i]*2.; 1645 } 1646 mol->Translate((const Vector *)&x); 1647 } 1648 break; 1649 case 'O': 1650 ExitFlag = 1; 1651 SaveFlag = true; 1652 cout << Verbose(1) << "Centering atoms in origin." << endl; 1653 mol->CenterOrigin((ofstream *)&cout, &x); 1654 mol->SetBoxDimension(&x); 1655 break; 1656 case 'r': 1657 ExitFlag = 1; 1658 SaveFlag = true; 1659 cout << Verbose(1) << "Converting config file from supposed old to new syntax." << endl; 1660 break; 1661 case 'F': 1662 case 'f': 1663 ExitFlag = 1; 1664 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1]))) { 1665 ExitFlag = 255; 1666 cerr << "Not enough or invalid arguments for fragmentation: -f <max. bond distance> <bond order>" << endl; 1667 } else { 1668 cout << "Fragmenting molecule with bond distance " << argv[argptr] << " angstroem, order of " << argv[argptr+1] << "." << endl; 1669 cout << Verbose(0) << "Creating connection matrix..." << endl; 1670 start = clock(); 1671 mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr++]), configuration.GetIsAngstroem()); 1672 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl; 1673 if (mol->first->next != mol->last) { 1674 ExitFlag = mol->FragmentMolecule((ofstream *)&cout, atoi(argv[argptr]), &configuration); 1675 } 1676 end = clock(); 1677 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl; 1678 argptr+=2; 1679 } 1680 break; 1681 case 'm': 1682 ExitFlag = 1; 1683 j = atoi(argv[argptr++]); 1684 if ((j<0) || (j>1)) { 1685 cerr << Verbose(1) << "ERROR: Argument of '-m' should be either 0 for no-rotate or 1 for rotate." << endl; 1686 j = 0; 1687 } 1688 if (j) { 1689 SaveFlag = true; 1690 cout << Verbose(0) << "Converting to prinicipal axis system." << endl; 1691 } else 1692 cout << Verbose(0) << "Evaluating prinicipal axis." << endl; 1693 mol->PrincipalAxisSystem((ofstream *)&cout, (bool)j); 1694 break; 1695 case 'o': 1696 ExitFlag = 1; 1697 if ((argptr >= argc) || (argv[argptr][0] == '-')){ 1698 ExitFlag = 255; 1699 cerr << "Not enough or invalid arguments given for convex envelope: -o <tecplot output file>" << endl; 1700 } else { 1701 cout << Verbose(0) << "Evaluating volume of the convex envelope."; 1702 cout << Verbose(1) << "Storing tecplot data in " << argv[argptr] << "." << endl; 1703 VolumeOfConvexEnvelope((ofstream *)&cout, argv[argptr], &configuration, NULL, mol); 1704 argptr+=1; 1705 } 1706 break; 1707 case 'U': 1708 ExitFlag = 1; 1709 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) ) { 1710 ExitFlag = 255; 1711 cerr << "Not enough or invalid arguments given for suspension with specified volume: -U <volume> <density>" << endl; 1712 volume = -1; // for case 'u': don't print error again 1713 } else { 1714 volume = atof(argv[argptr++]); 1715 cout << Verbose(0) << "Using " << volume << " angstrom^3 as the volume instead of convex envelope one's." << endl; 1716 } 1717 case 'u': 1718 ExitFlag = 1; 1719 if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) { 1720 if (volume != -1) 1721 ExitFlag = 255; 1722 cerr << "Not enough arguments given for suspension: -u <density>" << endl; 1723 } else { 1724 double density; 1725 SaveFlag = true; 1726 cout << Verbose(0) << "Evaluating necessary cell volume for a cluster suspended in water."; 1727 density = atof(argv[argptr++]); 1728 if (density < 1.0) { 1729 cerr << Verbose(0) << "Density must be greater than 1.0g/cm^3 !" << endl; 1730 density = 1.3; 1731 } 1732 // for(int i=0;i<NDIM;i++) { 1733 // repetition[i] = atoi(argv[argptr++]); 1734 // if (repetition[i] < 1) 1735 // cerr << Verbose(0) << "ERROR: repetition value must be greater 1!" << endl; 1736 // repetition[i] = 1; 1737 // } 1738 PrepareClustersinWater((ofstream *)&cout, &configuration, mol, volume, density); // if volume == 0, will calculate from ConvexEnvelope 1739 } 1740 break; 1741 case 'd': 1742 ExitFlag = 1; 1743 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) { 1744 ExitFlag = 255; 1745 cerr << "Not enough or invalid arguments given for repeating cells: -d <repeat_x> <repeat_y> <repeat_z>" << endl; 1746 } else { 1747 SaveFlag = true; 1748 for (int axis = 1; axis <= NDIM; axis++) { 1749 int faktor = atoi(argv[argptr++]); 1750 int count; 1751 element ** Elements; 1752 Vector ** vectors; 1753 if (faktor < 1) { 1754 cerr << Verbose(0) << "ERROR: Repetition faktor mus be greater than 1!" << endl; 1755 faktor = 1; 1756 } 1757 mol->CountAtoms((ofstream *)&cout); // recount atoms 1758 if (mol->AtomCount != 0) { // if there is more than none 1759 count = mol->AtomCount; // is changed becausing of adding, thus has to be stored away beforehand 1760 Elements = new element *[count]; 1761 vectors = new Vector *[count]; 1762 j = 0; 1763 first = mol->start; 1764 while (first->next != mol->end) { // make a list of all atoms with coordinates and element 1765 first = first->next; 1766 Elements[j] = first->type; 1767 vectors[j] = &first->x; 1768 j++; 1769 } 1770 if (count != j) 1771 cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl; 1772 x.Zero(); 1773 y.Zero(); 1774 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 1775 for (int i=1;i<faktor;i++) { // then add this list with respective translation factor times 1776 x.AddVector(&y); // per factor one cell width further 1777 for (int k=count;k--;) { // go through every atom of the original cell 1778 first = new atom(); // create a new body 1779 first->x.CopyVector(vectors[k]); // use coordinate of original atom 1780 first->x.AddVector(&x); // translate the coordinates 1781 first->type = Elements[k]; // insert original element 1782 mol->AddAtom(first); // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...) 1783 } 1784 } 1785 // free memory 1786 delete[](Elements); 1787 delete[](vectors); 1788 // correct cell size 1789 if (axis < 0) { // if sign was negative, we have to translate everything 1790 x.Zero(); 1791 x.AddVector(&y); 1792 x.Scale(-(faktor-1)); 1793 mol->Translate(&x); 1794 } 1795 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor; 1796 } 1797 } 1798 } 1799 break; 1800 default: // no match? Step on 1801 if ((argptr < argc) && (argv[argptr][0] != '-')) // if it started with a '-' we've already made a step! 1802 argptr++; 1803 break; 1804 } 1805 } 1806 } else argptr++; 1807 } while (argptr < argc); 1808 if (SaveFlag) 1809 SaveConfig(ConfigFileName, &configuration, periode, molecules); 1810 if ((ExitFlag >= 1)) { 1811 delete(mol); 1812 delete(periode); 1813 return (ExitFlag); 1814 } 1815 } else { // no arguments, hence scan the elements db 1816 if (periode->LoadPeriodentafel(PathToDatabases)) 1817 cout << Verbose(0) << "Element list loaded successfully." << endl; 1818 else 1819 cout << Verbose(0) << "Element list loading failed." << endl; 1820 configuration.RetrieveConfigPathAndName("main_pcp_linux"); 1821 } 1822 return(0); 1823 1823 }; 1824 1824 … … 1827 1827 int main(int argc, char **argv) 1828 1828 { 1829 periodentafel *periode = new periodentafel; // and a period table of all elements1830 MoleculeListClass *molecules = new MoleculeListClass; // list of all molecules1831 molecule *mol = NULL;1832 config configuration;1833 double tmp1;1834 atom *first, *second;1835 char choice;// menu choice char1836 Vector x,y,z,n;// coordinates for absolute point in cell volume1837 bool valid; // flag if input was valid or not1838 ifstream test;1839 ofstream output;1840 string line;1841 char *ConfigFileName = NULL;1842 char *ElementsFileName = NULL;1843 int Z;1844 int j, axis, count, faktor;1845 1846 // =========================== PARSE COMMAND LINE OPTIONS ====================================1847 j = ParseCommandLineOptions(argc, argv, molecules, periode, configuration, ConfigFileName, ElementsFileName);1848 if (j == 1) return 0; // just for -v and -h options1849 if (j) return j;// something went wrong1850 1851 // General stuff1852 if (molecules->ListOfMolecules.size() == 0) {1829 periodentafel *periode = new periodentafel; // and a period table of all elements 1830 MoleculeListClass *molecules = new MoleculeListClass; // list of all molecules 1831 molecule *mol = NULL; 1832 config configuration; 1833 double tmp1; 1834 atom *first, *second; 1835 char choice; // menu choice char 1836 Vector x,y,z,n; // coordinates for absolute point in cell volume 1837 bool valid; // flag if input was valid or not 1838 ifstream test; 1839 ofstream output; 1840 string line; 1841 char *ConfigFileName = NULL; 1842 char *ElementsFileName = NULL; 1843 int Z; 1844 int j, axis, count, faktor; 1845 1846 // =========================== PARSE COMMAND LINE OPTIONS ==================================== 1847 j = ParseCommandLineOptions(argc, argv, molecules, periode, configuration, ConfigFileName, ElementsFileName); 1848 if (j == 1) return 0; // just for -v and -h options 1849 if (j) return j; // something went wrong 1850 1851 // General stuff 1852 if (molecules->ListOfMolecules.size() == 0) { 1853 1853 mol = new molecule(periode); 1854 1854 if (mol->cell_size[0] == 0.) { … … 1860 1860 } 1861 1861 molecules->insert(mol); 1862 }1863 1864 // =========================== START INTERACTIVE SESSION ====================================1865 1866 // now the main construction loop1867 cout << Verbose(0) << endl << "Now comes the real construction..." << endl;1868 do {1869 cout << Verbose(0) << endl << endl;1870 cout << Verbose(0) << "============Molecule list=======================" << endl;1871 molecules->Enumerate((ofstream *)&cout);1872 cout << Verbose(0) << "============Menu===============================" << endl;1862 } 1863 1864 // =========================== START INTERACTIVE SESSION ==================================== 1865 1866 // now the main construction loop 1867 cout << Verbose(0) << endl << "Now comes the real construction..." << endl; 1868 do { 1869 cout << Verbose(0) << endl << endl; 1870 cout << Verbose(0) << "============Molecule list=======================" << endl; 1871 molecules->Enumerate((ofstream *)&cout); 1872 cout << Verbose(0) << "============Menu===============================" << endl; 1873 1873 cout << Verbose(0) << "a - set molecule (in)active" << endl; 1874 1874 cout << Verbose(0) << "e - edit new molecules" << endl; … … 1886 1886 cin >> choice; 1887 1887 1888 switch (choice) {1889 case 'a': // (in)activate molecule1888 switch (choice) { 1889 case 'a': // (in)activate molecule 1890 1890 { 1891 1891 cout << "Enter index of molecule: "; … … 1897 1897 (*ListRunner)->ActiveFlag = !(*ListRunner)->ActiveFlag; 1898 1898 } 1899 break;1900 1901 case 'c': // edit each field of the configuration1902 configuration.Edit();1903 break;1899 break; 1900 1901 case 'c': // edit each field of the configuration 1902 configuration.Edit(); 1903 break; 1904 1904 1905 1905 case 'e': // create molecule … … 1919 1919 break; 1920 1920 1921 case 'q': // quit1922 break;1923 1924 case 's': // save to config file1925 SaveConfig(ConfigFileName, &configuration, periode, molecules);1926 break;1927 1928 case 'T':1929 testroutine(molecules);1930 break;1931 1932 default:1933 break;1934 };1935 } while (choice != 'q');1936 1937 // save element data base1938 if (periode->StorePeriodentafel(ElementsFileName)) //ElementsFileName1939 cout << Verbose(0) << "Saving of elements.db successful." << endl;1940 else1941 cout << Verbose(0) << "Saving of elements.db failed." << endl;1942 1943 delete(molecules);1944 delete(periode);1945 return (0);1921 case 'q': // quit 1922 break; 1923 1924 case 's': // save to config file 1925 SaveConfig(ConfigFileName, &configuration, periode, molecules); 1926 break; 1927 1928 case 'T': 1929 testroutine(molecules); 1930 break; 1931 1932 default: 1933 break; 1934 }; 1935 } while (choice != 'q'); 1936 1937 // save element data base 1938 if (periode->StorePeriodentafel(ElementsFileName)) //ElementsFileName 1939 cout << Verbose(0) << "Saving of elements.db successful." << endl; 1940 else 1941 cout << Verbose(0) << "Saving of elements.db failed." << endl; 1942 1943 delete(molecules); 1944 delete(periode); 1945 return (0); 1946 1946 } 1947 1947 -
src/molecules.cpp
ra5b2c3a r375b458 16 16 double LSQ (const gsl_vector * x, void * params) 17 17 { 18 double sum = 0.;19 struct LSQ_params *par = (struct LSQ_params *)params;20 Vector **vectors = par->vectors;21 int num = par->num;22 23 for (int i=num;i--;) {24 for(int j=NDIM;j--;)25 sum += (gsl_vector_get(x,j) - (vectors[i])->x[j])*(gsl_vector_get(x,j) - (vectors[i])->x[j]);26 }27 28 return sum;18 double sum = 0.; 19 struct LSQ_params *par = (struct LSQ_params *)params; 20 Vector **vectors = par->vectors; 21 int num = par->num; 22 23 for (int i=num;i--;) { 24 for(int j=NDIM;j--;) 25 sum += (gsl_vector_get(x,j) - (vectors[i])->x[j])*(gsl_vector_get(x,j) - (vectors[i])->x[j]); 26 } 27 28 return sum; 29 29 }; 30 30 … … 36 36 molecule::molecule(periodentafel *teil) 37 37 { 38 // init atom chain list39 start = new atom;40 end = new atom;41 start->father = NULL;42 end->father = NULL;43 link(start,end);44 // init bond chain list45 first = new bond(start, end, 1, -1);46 last = new bond(start, end, 1, -1);47 link(first,last);48 // other stuff49 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");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 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);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 if (pointer != NULL) {92 pointer->sort = &pointer->nr;93 pointer->nr = last_atom++;// increase number within molecule94 AtomCount++;95 if (pointer->type != NULL) {96 if (ElementsInMolecule[pointer->type->Z] == 0)97 ElementCount++;98 ElementsInMolecule[pointer->type->Z]++; // increase number of elements99 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 } else109 return false;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 if (pointer != NULL) {120 atom *walker = new atom();121 walker->type = pointer->type;// copy element of atom122 walker->x.CopyVector(&pointer->x); // copy coordination123 walker->v.CopyVector(&pointer->v); // copy velocity124 walker->FixedIon = pointer->FixedIon;125 walker->sort = &walker->nr;126 walker->nr = last_atom++;// increase number within molecule127 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 } else136 return NULL;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 * *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 two146 * replacing hydrogens shall lie in. Now, all remains to do is take the usual hydrogen double bond angle for the147 * element of *origin and form the sin/cos admixture of both plane vectors for the new coordinates of the two148 * hydrogens forming this angle with *origin.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 * triangle formed by the to be added hydrogens are not equal to the typical bond distance \f$l\f$ but have to be151 * 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 creates156 * 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 that158 * 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$.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 number of bonds in \a **BondList170 * \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 bond *FirstBond = NULL, *SecondBond = NULL; // Other bonds in double bond case to determine "other" plane182 atom *FirstOtherAtom = NULL, *SecondOtherAtom = NULL, *ThirdOtherAtom = NULL; // pointer to hydrogen atoms to be added183 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 bond *Binder = NULL;187 double *matrix;188 189 // *out << Verbose(3) << "Begin of AddHydrogenReplacementAtom." << endl;190 // create vector in direction of bond191 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 periodically196 // the problem is not the H being out of the box, but InBondvector have the wrong direction197 // 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 distance206 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 translation212 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 finished218 219 InBondvector.Normalize();220 // get typical bond length and store as scale factor for later221 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 bonds232 switch(TopBond->BondDegree) {233 case 1:234 FirstOtherAtom = new atom();// new atom235 FirstOtherAtom->type = elemente->FindElement(1);// element is Hydrogen236 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity237 FirstOtherAtom->FixedIon = TopReplacement->FixedIon;238 if (TopReplacement->type->Z == 1) { // neither rescale nor replace if it's already hydrogen239 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 father243 }244 InBondvector.Scale(&BondRescale);// rescale the distance vector to Hydrogen bond length245 FirstOtherAtom->x.CopyVector(&TopOrigin->x); // set coordination to origin ...246 FirstOtherAtom->x.AddVector(&InBondvector);// ... and add distance vector to replacement atom247 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 check257 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 all275 // *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 *origin278 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 plane286 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 velocity296 FirstOtherAtom->FixedIon = TopReplacement->FixedIon;297 SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity298 SecondOtherAtom->FixedIon = TopReplacement->FixedIon;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 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 BondDistance322 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 atom325 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i];326 SecondOtherAtom->x.x[i] += TopOrigin->x.x[i];327 }328 // ... and add to molecule329 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 velocity353 FirstOtherAtom->FixedIon = TopReplacement->FixedIon;354 SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity355 SecondOtherAtom->FixedIon = TopReplacement->FixedIon;356 ThirdOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity357 ThirdOtherAtom->FixedIon = TopReplacement->FixedIon;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 // we need to vectors orthonormal the InBondvector363 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 atoms373 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 // *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 BondDistance392 // FirstOtherAtom->x.Scale(&BondRescale);393 // SecondOtherAtom->x.Scale(&BondRescale);394 // ThirdOtherAtom->x.Scale(&BondRescale);395 396 // and relative to *origin atom397 FirstOtherAtom->x.AddVector(&TopOrigin->x);398 SecondOtherAtom->x.AddVector(&TopOrigin->x);399 ThirdOtherAtom->x.AddVector(&TopOrigin->x);400 401 // ... and add to molecule402 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;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 istringstream *input = NULL;442 int NumberOfAtoms = 0; // atom number in xyz read443 int i, j; // loop variables444 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 xyzfile.open(filename.c_str());451 if (!xyzfile)452 return false;453 454 getline(xyzfile,line,'\n'); // Read numer of atoms in file455 input = new istringstream(line);456 *input >> NumberOfAtoms;457 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl;458 getline(xyzfile,line,'\n'); // Read comment459 cout << Verbose(1) << "Comment: " << line << endl;460 461 if (MDSteps == 0) // no atoms yet present462 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 molecule490 delete(item);491 }492 xyzfile.close();493 delete(input);494 return true;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 molecule *copy = new molecule(elemente);503 atom *CurrentAtom = NULL;504 atom *LeftAtom = NULL, *RightAtom = NULL;505 atom *Walker = NULL;506 507 // copy all atoms508 Walker = start;509 while(Walker->next != end) {510 Walker = Walker->next;511 CurrentAtom = copy->AddCopyAtom(Walker);512 }513 514 // copy all bonds515 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 molecule520 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 fathers539 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 itself543 Walker->father = Walker;// set father to itself (copy of a whole molecule)544 else545 Walker->father = Walker->father->father;// set father to original's father546 }547 // copy values548 copy->CountAtoms((ofstream *)&cout);549 copy->CountElements();550 if (first->next != last) {// if adjaceny list is present551 copy->BondDistance = BondDistance;552 copy->CreateListOfBondsPerAtom((ofstream *)&cout);553 }554 555 return copy;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 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;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 //cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl;586 removewithoutcheck(pointer);587 return true;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 cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl;598 return false;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 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];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 … … 633 633 bool molecule::CenterInBox(ofstream *out, Vector *BoxLengths) 634 634 { 635 bool status = true;636 atom *ptr = NULL;637 Vector *min = new Vector;638 Vector *max = new Vector;639 640 // gather min and max for each axis641 ptr = start->next;// start at first in list642 if (ptr != end) {//list not empty?643 for (int i=NDIM;i--;) {644 max->x[i] = ptr->x.x[i];645 min->x[i] = ptr->x.x[i];646 }647 while (ptr->next != end) {// continue with second if present648 ptr = ptr->next;649 //ptr->Output(1,1,out);650 for (int i=NDIM;i--;) {651 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i];652 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i];653 }654 }655 }656 // sanity check657 for(int i=NDIM;i--;) {658 if (max->x[i] - min->x[i] > BoxLengths->x[i])659 status = false;660 }661 // warn if check failed662 if (!status)663 *out << "WARNING: molecule is bigger than defined box!" << endl;664 else {// else center in box665 max->AddVector(min);666 max->Scale(-1.);667 max->AddVector(BoxLengths);668 max->Scale(0.5);669 Translate(max);670 }671 672 // free and exit673 delete(min);674 delete(max);675 return status;635 bool status = true; 636 atom *ptr = NULL; 637 Vector *min = new Vector; 638 Vector *max = new Vector; 639 640 // gather min and max for each axis 641 ptr = start->next; // start at first in list 642 if (ptr != end) { //list not empty? 643 for (int i=NDIM;i--;) { 644 max->x[i] = ptr->x.x[i]; 645 min->x[i] = ptr->x.x[i]; 646 } 647 while (ptr->next != end) { // continue with second if present 648 ptr = ptr->next; 649 //ptr->Output(1,1,out); 650 for (int i=NDIM;i--;) { 651 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i]; 652 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i]; 653 } 654 } 655 } 656 // sanity check 657 for(int i=NDIM;i--;) { 658 if (max->x[i] - min->x[i] > BoxLengths->x[i]) 659 status = false; 660 } 661 // warn if check failed 662 if (!status) 663 *out << "WARNING: molecule is bigger than defined box!" << endl; 664 else { // else center in box 665 max->AddVector(min); 666 max->Scale(-1.); 667 max->AddVector(BoxLengths); 668 max->Scale(0.5); 669 Translate(max); 670 } 671 672 // free and exit 673 delete(min); 674 delete(max); 675 return status; 676 676 }; 677 677 … … 682 682 void molecule::CenterEdge(ofstream *out, Vector *max) 683 683 { 684 Vector *min = new Vector;685 686 // *out << Verbose(3) << "Begin of CenterEdge." << endl;687 atom *ptr = start->next;// start at first in list688 if (ptr != end) {//list not empty?689 for (int i=NDIM;i--;) {690 max->x[i] = ptr->x.x[i];691 min->x[i] = ptr->x.x[i];692 }693 while (ptr->next != end) {// continue with second if present694 ptr = ptr->next;695 //ptr->Output(1,1,out);696 for (int i=NDIM;i--;) {697 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i];698 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i];699 }700 }701 // *out << Verbose(4) << "Maximum is ";702 // max->Output(out);703 // *out << ", Minimum is ";704 // min->Output(out);705 // *out << endl;706 min->Scale(-1.);707 max->AddVector(min);708 Translate(min);709 }710 delete(min);711 // *out << Verbose(3) << "End of CenterEdge." << endl;684 Vector *min = new Vector; 685 686 // *out << Verbose(3) << "Begin of CenterEdge." << endl; 687 atom *ptr = start->next; // start at first in list 688 if (ptr != end) { //list not empty? 689 for (int i=NDIM;i--;) { 690 max->x[i] = ptr->x.x[i]; 691 min->x[i] = ptr->x.x[i]; 692 } 693 while (ptr->next != end) { // continue with second if present 694 ptr = ptr->next; 695 //ptr->Output(1,1,out); 696 for (int i=NDIM;i--;) { 697 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i]; 698 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i]; 699 } 700 } 701 // *out << Verbose(4) << "Maximum is "; 702 // max->Output(out); 703 // *out << ", Minimum is "; 704 // min->Output(out); 705 // *out << endl; 706 min->Scale(-1.); 707 max->AddVector(min); 708 Translate(min); 709 } 710 delete(min); 711 // *out << Verbose(3) << "End of CenterEdge." << endl; 712 712 }; 713 713 … … 718 718 void molecule::CenterOrigin(ofstream *out, Vector *center) 719 719 { 720 int Num = 0;721 atom *ptr = start->next;// start at first in list722 723 for(int i=NDIM;i--;) // zero center vector724 center->x[i] = 0.;725 726 if (ptr != end) {//list not empty?727 while (ptr->next != end) {// continue with second if present728 ptr = ptr->next;729 Num++;730 center->AddVector(&ptr->x);731 }732 center->Scale(-1./Num); // divide through total number (and sign for direction)733 Translate(center);734 }720 int Num = 0; 721 atom *ptr = start->next; // start at first in list 722 723 for(int i=NDIM;i--;) // zero center vector 724 center->x[i] = 0.; 725 726 if (ptr != end) { //list not empty? 727 while (ptr->next != end) { // continue with second if present 728 ptr = ptr->next; 729 Num++; 730 center->AddVector(&ptr->x); 731 } 732 center->Scale(-1./Num); // divide through total number (and sign for direction) 733 Translate(center); 734 } 735 735 }; 736 736 … … 741 741 Vector * molecule::DetermineCenterOfAll(ofstream *out) 742 742 { 743 atom *ptr = start->next;// start at first in list744 Vector *a = new Vector();745 Vector tmp;746 double Num = 0;747 748 a->Zero();749 750 if (ptr != end) {//list not empty?751 while (ptr->next != end) {// continue with second if present752 ptr = ptr->next;753 Num += 1.;754 tmp.CopyVector(&ptr->x);755 a->AddVector(&tmp);756 }757 a->Scale(-1./Num); // divide through total mass (and sign for direction)758 }759 //cout << Verbose(1) << "Resulting center of gravity: ";760 //a->Output(out);761 //cout << endl;762 return a;743 atom *ptr = start->next; // start at first in list 744 Vector *a = new Vector(); 745 Vector tmp; 746 double Num = 0; 747 748 a->Zero(); 749 750 if (ptr != end) { //list not empty? 751 while (ptr->next != end) { // continue with second if present 752 ptr = ptr->next; 753 Num += 1.; 754 tmp.CopyVector(&ptr->x); 755 a->AddVector(&tmp); 756 } 757 a->Scale(-1./Num); // divide through total mass (and sign for direction) 758 } 759 //cout << Verbose(1) << "Resulting center of gravity: "; 760 //a->Output(out); 761 //cout << endl; 762 return a; 763 763 }; 764 764 … … 769 769 Vector * molecule::DetermineCenterOfGravity(ofstream *out) 770 770 { 771 atom *ptr = start->next;// start at first in list772 Vector *a = new Vector();773 Vector tmp;774 double Num = 0;775 776 a->Zero();777 778 if (ptr != end) {//list not empty?779 while (ptr->next != end) {// continue with second if present780 ptr = ptr->next;781 Num += ptr->type->mass;782 tmp.CopyVector(&ptr->x);783 tmp.Scale(ptr->type->mass);// scale by mass784 a->AddVector(&tmp);785 }786 a->Scale(-1./Num); // divide through total mass (and sign for direction)787 }788 // *out << Verbose(1) << "Resulting center of gravity: ";789 // a->Output(out);790 // *out << endl;791 return a;771 atom *ptr = start->next; // start at first in list 772 Vector *a = new Vector(); 773 Vector tmp; 774 double Num = 0; 775 776 a->Zero(); 777 778 if (ptr != end) { //list not empty? 779 while (ptr->next != end) { // continue with second if present 780 ptr = ptr->next; 781 Num += ptr->type->mass; 782 tmp.CopyVector(&ptr->x); 783 tmp.Scale(ptr->type->mass); // scale by mass 784 a->AddVector(&tmp); 785 } 786 a->Scale(-1./Num); // divide through total mass (and sign for direction) 787 } 788 // *out << Verbose(1) << "Resulting center of gravity: "; 789 // a->Output(out); 790 // *out << endl; 791 return a; 792 792 }; 793 793 … … 798 798 void molecule::CenterGravity(ofstream *out, Vector *center) 799 799 { 800 if (center == NULL) {801 DetermineCenter(*center);802 Translate(center);803 delete(center);804 } else {805 Translate(center);806 }800 if (center == NULL) { 801 DetermineCenter(*center); 802 Translate(center); 803 delete(center); 804 } else { 805 Translate(center); 806 } 807 807 }; 808 808 … … 812 812 void molecule::Scale(double **factor) 813 813 { 814 atom *ptr = start;815 816 while (ptr->next != end) {817 ptr = ptr->next;818 for (int j=0;j<MDSteps;j++)819 Trajectories[ptr].R.at(j).Scale(factor);820 ptr->x.Scale(factor);821 }814 atom *ptr = start; 815 816 while (ptr->next != end) { 817 ptr = ptr->next; 818 for (int j=0;j<MDSteps;j++) 819 Trajectories[ptr].R.at(j).Scale(factor); 820 ptr->x.Scale(factor); 821 } 822 822 }; 823 823 … … 827 827 void molecule::Translate(const Vector *trans) 828 828 { 829 atom *ptr = start;830 831 while (ptr->next != end) {832 ptr = ptr->next;833 for (int j=0;j<MDSteps;j++)834 Trajectories[ptr].R.at(j).Translate(trans);835 ptr->x.Translate(trans);836 }829 atom *ptr = start; 830 831 while (ptr->next != end) { 832 ptr = ptr->next; 833 for (int j=0;j<MDSteps;j++) 834 Trajectories[ptr].R.at(j).Translate(trans); 835 ptr->x.Translate(trans); 836 } 837 837 }; 838 838 … … 842 842 void molecule::Mirror(const Vector *n) 843 843 { 844 atom *ptr = start;845 846 while (ptr->next != end) {847 ptr = ptr->next;848 for (int j=0;j<MDSteps;j++)849 Trajectories[ptr].R.at(j).Mirror(n);850 ptr->x.Mirror(n);851 }844 atom *ptr = start; 845 846 while (ptr->next != end) { 847 ptr = ptr->next; 848 for (int j=0;j<MDSteps;j++) 849 Trajectories[ptr].R.at(j).Mirror(n); 850 ptr->x.Mirror(n); 851 } 852 852 }; 853 853 … … 857 857 void molecule::DetermineCenter(Vector &Center) 858 858 { 859 atom *Walker = start;860 bond *Binder = NULL;861 double *matrix = ReturnFullMatrixforSymmetric(cell_size);862 double tmp;863 bool flag;864 Vector Testvector, Translationvector;865 866 do {867 Center.Zero();868 flag = true;869 while (Walker->next != end) {870 Walker = Walker->next;859 atom *Walker = start; 860 bond *Binder = NULL; 861 double *matrix = ReturnFullMatrixforSymmetric(cell_size); 862 double tmp; 863 bool flag; 864 Vector Testvector, Translationvector; 865 866 do { 867 Center.Zero(); 868 flag = true; 869 while (Walker->next != end) { 870 Walker = Walker->next; 871 871 #ifdef ADDHYDROGEN 872 if (Walker->type->Z != 1) {872 if (Walker->type->Z != 1) { 873 873 #endif 874 Testvector.CopyVector(&Walker->x);875 Testvector.InverseMatrixMultiplication(matrix);876 Translationvector.Zero();877 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {878 Binder = ListOfBondsPerAtom[Walker->nr][i];879 if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing880 for (int j=0;j<NDIM;j++) {881 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j];882 if ((fabs(tmp)) > BondDistance) {883 flag = false;884 cout << Verbose(0) << "Hit: atom " << Walker->Name << " in bond " << *Binder << " has to be shifted due to " << tmp << "." << endl;885 if (tmp > 0)886 Translationvector.x[j] -= 1.;887 else888 Translationvector.x[j] += 1.;889 }890 }891 }892 Testvector.AddVector(&Translationvector);893 Testvector.MatrixMultiplication(matrix);894 Center.AddVector(&Testvector);895 cout << Verbose(1) << "vector is: ";896 Testvector.Output((ofstream *)&cout);897 cout << endl;874 Testvector.CopyVector(&Walker->x); 875 Testvector.InverseMatrixMultiplication(matrix); 876 Translationvector.Zero(); 877 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) { 878 Binder = ListOfBondsPerAtom[Walker->nr][i]; 879 if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing 880 for (int j=0;j<NDIM;j++) { 881 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j]; 882 if ((fabs(tmp)) > BondDistance) { 883 flag = false; 884 cout << Verbose(0) << "Hit: atom " << Walker->Name << " in bond " << *Binder << " has to be shifted due to " << tmp << "." << endl; 885 if (tmp > 0) 886 Translationvector.x[j] -= 1.; 887 else 888 Translationvector.x[j] += 1.; 889 } 890 } 891 } 892 Testvector.AddVector(&Translationvector); 893 Testvector.MatrixMultiplication(matrix); 894 Center.AddVector(&Testvector); 895 cout << Verbose(1) << "vector is: "; 896 Testvector.Output((ofstream *)&cout); 897 cout << endl; 898 898 #ifdef ADDHYDROGEN 899 // now also change all hydrogens900 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {901 Binder = ListOfBondsPerAtom[Walker->nr][i];902 if (Binder->GetOtherAtom(Walker)->type->Z == 1) {903 Testvector.CopyVector(&Binder->GetOtherAtom(Walker)->x);904 Testvector.InverseMatrixMultiplication(matrix);905 Testvector.AddVector(&Translationvector);906 Testvector.MatrixMultiplication(matrix);907 Center.AddVector(&Testvector);908 cout << Verbose(1) << "Hydrogen vector is: ";909 Testvector.Output((ofstream *)&cout);910 cout << endl;911 }912 }913 }899 // now also change all hydrogens 900 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) { 901 Binder = ListOfBondsPerAtom[Walker->nr][i]; 902 if (Binder->GetOtherAtom(Walker)->type->Z == 1) { 903 Testvector.CopyVector(&Binder->GetOtherAtom(Walker)->x); 904 Testvector.InverseMatrixMultiplication(matrix); 905 Testvector.AddVector(&Translationvector); 906 Testvector.MatrixMultiplication(matrix); 907 Center.AddVector(&Testvector); 908 cout << Verbose(1) << "Hydrogen vector is: "; 909 Testvector.Output((ofstream *)&cout); 910 cout << endl; 911 } 912 } 913 } 914 914 #endif 915 }916 } while (!flag);917 Free((void **)&matrix, "molecule::DetermineCenter: *matrix");918 Center.Scale(1./(double)AtomCount);915 } 916 } while (!flag); 917 Free((void **)&matrix, "molecule::DetermineCenter: *matrix"); 918 Center.Scale(1./(double)AtomCount); 919 919 }; 920 920 … … 925 925 void molecule::PrincipalAxisSystem(ofstream *out, bool DoRotate) 926 926 { 927 atom *ptr = start;// start at first in list928 double InertiaTensor[NDIM*NDIM];929 Vector *CenterOfGravity = DetermineCenterOfGravity(out);930 931 CenterGravity(out, CenterOfGravity);932 933 // reset inertia tensor934 for(int i=0;i<NDIM*NDIM;i++)935 InertiaTensor[i] = 0.;936 937 // sum up inertia tensor938 while (ptr->next != end) {939 ptr = ptr->next;940 Vector x;941 x.CopyVector(&ptr->x);942 //x.SubtractVector(CenterOfGravity);943 InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]);944 InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]);945 InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]);946 InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]);947 InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]);948 InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]);949 InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]);950 InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]);951 InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]);952 }953 // print InertiaTensor for debugging954 *out << "The inertia tensor is:" << endl;955 for(int i=0;i<NDIM;i++) {956 for(int j=0;j<NDIM;j++)957 *out << InertiaTensor[i*NDIM+j] << " ";958 *out << endl;959 }960 *out << endl;961 962 // diagonalize to determine principal axis system963 gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(NDIM);964 gsl_matrix_view m = gsl_matrix_view_array(InertiaTensor, NDIM, NDIM);965 gsl_vector *eval = gsl_vector_alloc(NDIM);966 gsl_matrix *evec = gsl_matrix_alloc(NDIM, NDIM);967 gsl_eigen_symmv(&m.matrix, eval, evec, T);968 gsl_eigen_symmv_free(T);969 gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC);970 971 for(int i=0;i<NDIM;i++) {972 *out << Verbose(1) << "eigenvalue = " << gsl_vector_get(eval, i);973 *out << ", eigenvector = (" << evec->data[i * evec->tda + 0] << "," << evec->data[i * evec->tda + 1] << "," << evec->data[i * evec->tda + 2] << ")" << endl;974 }975 976 // check whether we rotate or not977 if (DoRotate) {978 *out << Verbose(1) << "Transforming molecule into PAS ... ";979 // the eigenvectors specify the transformation matrix980 ptr = start;981 while (ptr->next != end) {982 ptr = ptr->next;983 for (int j=0;j<MDSteps;j++)984 Trajectories[ptr].R.at(j).MatrixMultiplication(evec->data);985 ptr->x.MatrixMultiplication(evec->data);986 }987 *out << "done." << endl;988 989 // summing anew for debugging (resulting matrix has to be diagonal!)990 // reset inertia tensor991 for(int i=0;i<NDIM*NDIM;i++)992 InertiaTensor[i] = 0.;993 994 // sum up inertia tensor995 ptr = start;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 debugging1012 *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 1021 // free everything1022 delete(CenterOfGravity);1023 gsl_vector_free(eval);1024 gsl_matrix_free(evec);927 atom *ptr = start; // start at first in list 928 double InertiaTensor[NDIM*NDIM]; 929 Vector *CenterOfGravity = DetermineCenterOfGravity(out); 930 931 CenterGravity(out, CenterOfGravity); 932 933 // reset inertia tensor 934 for(int i=0;i<NDIM*NDIM;i++) 935 InertiaTensor[i] = 0.; 936 937 // sum up inertia tensor 938 while (ptr->next != end) { 939 ptr = ptr->next; 940 Vector x; 941 x.CopyVector(&ptr->x); 942 //x.SubtractVector(CenterOfGravity); 943 InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]); 944 InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]); 945 InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]); 946 InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]); 947 InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]); 948 InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]); 949 InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]); 950 InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]); 951 InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]); 952 } 953 // print InertiaTensor for debugging 954 *out << "The inertia tensor is:" << endl; 955 for(int i=0;i<NDIM;i++) { 956 for(int j=0;j<NDIM;j++) 957 *out << InertiaTensor[i*NDIM+j] << " "; 958 *out << endl; 959 } 960 *out << endl; 961 962 // diagonalize to determine principal axis system 963 gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(NDIM); 964 gsl_matrix_view m = gsl_matrix_view_array(InertiaTensor, NDIM, NDIM); 965 gsl_vector *eval = gsl_vector_alloc(NDIM); 966 gsl_matrix *evec = gsl_matrix_alloc(NDIM, NDIM); 967 gsl_eigen_symmv(&m.matrix, eval, evec, T); 968 gsl_eigen_symmv_free(T); 969 gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC); 970 971 for(int i=0;i<NDIM;i++) { 972 *out << Verbose(1) << "eigenvalue = " << gsl_vector_get(eval, i); 973 *out << ", eigenvector = (" << evec->data[i * evec->tda + 0] << "," << evec->data[i * evec->tda + 1] << "," << evec->data[i * evec->tda + 2] << ")" << endl; 974 } 975 976 // check whether we rotate or not 977 if (DoRotate) { 978 *out << Verbose(1) << "Transforming molecule into PAS ... "; 979 // the eigenvectors specify the transformation matrix 980 ptr = start; 981 while (ptr->next != end) { 982 ptr = ptr->next; 983 for (int j=0;j<MDSteps;j++) 984 Trajectories[ptr].R.at(j).MatrixMultiplication(evec->data); 985 ptr->x.MatrixMultiplication(evec->data); 986 } 987 *out << "done." << endl; 988 989 // summing anew for debugging (resulting matrix has to be diagonal!) 990 // reset inertia tensor 991 for(int i=0;i<NDIM*NDIM;i++) 992 InertiaTensor[i] = 0.; 993 994 // sum up inertia tensor 995 ptr = start; 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 1021 // free everything 1022 delete(CenterOfGravity); 1023 gsl_vector_free(eval); 1024 gsl_matrix_free(evec); 1025 1025 }; 1026 1026 … … 1036 1036 bool molecule::VerletForceIntegration(char *file, double delta_t, bool IsAngstroem) 1037 1037 { 1038 element *runner = elemente->start;1039 atom *walker = NULL;1040 int AtomNo;1041 ifstream input(file);1042 string token;1043 stringstream item;1044 double a, IonMass;1045 ForceMatrix Force;1046 Vector tmpvector;1047 1048 CountElements();// make sure ElementsInMolecule is up to date1049 1050 // check file1051 if (input == NULL) {1052 return false;1053 } else {1054 // parse file into ForceMatrix1055 if (!Force.ParseMatrix(file, 0,0,0)) {1056 cerr << "Could not parse Force Matrix file " << file << "." << endl;1057 return false;1058 }1059 if (Force.RowCounter[0] != AtomCount) {1060 cerr << "Mismatch between number of atoms in file " << Force.RowCounter[0] << " and in molecule " << AtomCount << "." << endl;1061 return false;1062 }1063 // correct Forces1064 // for(int d=0;d<NDIM;d++)1065 // tmpvector.x[d] = 0.;1066 // for(int i=0;i<AtomCount;i++)1067 // for(int d=0;d<NDIM;d++) {1068 // tmpvector.x[d] += Force.Matrix[0][i][d+5];1069 // }1070 // for(int i=0;i<AtomCount;i++)1071 // for(int d=0;d<NDIM;d++) {1072 // Force.Matrix[0][i][d+5] -= tmpvector.x[d]/(double)AtomCount;1073 // }1074 // and perform Verlet integration for each atom with position, velocity and force vector1075 runner = elemente->start;1076 while (runner->next != elemente->end) { // go through every element1077 runner = runner->next;1078 IonMass = runner->mass;1079 a = delta_t*0.5/IonMass;// (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a1080 if (ElementsInMolecule[runner->Z]) { // if this element got atoms1081 AtomNo = 0;1082 walker = start;1083 while (walker->next != end) { // go through every atom of this element1084 walker = walker->next;1085 if (walker->type == runner) { // if this atom fits to element1086 // check size of vectors1087 if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) {1088 //cout << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl;1089 Trajectories[walker].R.resize(MDSteps+10);1090 Trajectories[walker].U.resize(MDSteps+10);1091 Trajectories[walker].F.resize(MDSteps+10);1092 }1093 // 1. calculate x(t+\delta t)1094 for (int d=0; d<NDIM; d++) {1095 Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5];1096 Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d];1097 Trajectories[walker].R.at(MDSteps).x[d] += delta_t*(Trajectories[walker].U.at(MDSteps-1).x[d]);1098 Trajectories[walker].R.at(MDSteps).x[d] += 0.5*delta_t*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d])/IonMass;// F = m * a and s = 0.5 * F/m * t^2 = F * a * t1099 }1100 // 2. Calculate v(t+\delta t)1101 for (int d=0; d<NDIM; d++) {1102 Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d];1103 Trajectories[walker].U.at(MDSteps).x[d] += 0.5*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d]+Trajectories[walker].F.at(MDSteps).x[d])/IonMass;1104 }1105 // cout << "Integrated position&velocity of step " << (MDSteps) << ": (";1106 // for (int d=0;d<NDIM;d++)1107 // cout << Trajectories[walker].R.at(MDSteps).x[d] << " ";// next step1108 // cout << ")\t(";1109 // for (int d=0;d<NDIM;d++)1110 // cout << Trajectories[walker].U.at(MDSteps).x[d] << " ";// next step1111 // cout << ")" << endl;1112 // next atom1113 AtomNo++;1114 }1115 }1116 }1117 }1118 }1119 // // correct velocities (rather momenta) so that center of mass remains motionless1120 // tmpvector.zero()1121 // IonMass = 0.;1122 // walker = start;1123 // while (walker->next != end) { // go through every atom1124 // walker = walker->next;1125 // IonMass += walker->type->mass;// sum up total mass1126 // for(int d=0;d<NDIM;d++) {1127 // tmpvector.x[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass;1128 // }1129 // }1130 // walker = start;1131 // while (walker->next != end) { // go through every atom of this element1132 // walker = walker->next;1133 // for(int d=0;d<NDIM;d++) {1134 // Trajectories[walker].U.at(MDSteps).x[d] -= tmpvector.x[d]*walker->type->mass/IonMass;1135 // }1136 // }1137 MDSteps++;1138 1139 1140 // exit1141 return true;1038 element *runner = elemente->start; 1039 atom *walker = NULL; 1040 int AtomNo; 1041 ifstream input(file); 1042 string token; 1043 stringstream item; 1044 double a, IonMass; 1045 ForceMatrix Force; 1046 Vector tmpvector; 1047 1048 CountElements(); // make sure ElementsInMolecule is up to date 1049 1050 // check file 1051 if (input == NULL) { 1052 return false; 1053 } else { 1054 // parse file into ForceMatrix 1055 if (!Force.ParseMatrix(file, 0,0,0)) { 1056 cerr << "Could not parse Force Matrix file " << file << "." << endl; 1057 return false; 1058 } 1059 if (Force.RowCounter[0] != AtomCount) { 1060 cerr << "Mismatch between number of atoms in file " << Force.RowCounter[0] << " and in molecule " << AtomCount << "." << endl; 1061 return false; 1062 } 1063 // correct Forces 1064 // for(int d=0;d<NDIM;d++) 1065 // tmpvector.x[d] = 0.; 1066 // for(int i=0;i<AtomCount;i++) 1067 // for(int d=0;d<NDIM;d++) { 1068 // tmpvector.x[d] += Force.Matrix[0][i][d+5]; 1069 // } 1070 // for(int i=0;i<AtomCount;i++) 1071 // for(int d=0;d<NDIM;d++) { 1072 // Force.Matrix[0][i][d+5] -= tmpvector.x[d]/(double)AtomCount; 1073 // } 1074 // and perform Verlet integration for each atom with position, velocity and force vector 1075 runner = elemente->start; 1076 while (runner->next != elemente->end) { // go through every element 1077 runner = runner->next; 1078 IonMass = runner->mass; 1079 a = delta_t*0.5/IonMass; // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a 1080 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1081 AtomNo = 0; 1082 walker = start; 1083 while (walker->next != end) { // go through every atom of this element 1084 walker = walker->next; 1085 if (walker->type == runner) { // if this atom fits to element 1086 // check size of vectors 1087 if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) { 1088 //cout << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl; 1089 Trajectories[walker].R.resize(MDSteps+10); 1090 Trajectories[walker].U.resize(MDSteps+10); 1091 Trajectories[walker].F.resize(MDSteps+10); 1092 } 1093 // 1. calculate x(t+\delta t) 1094 for (int d=0; d<NDIM; d++) { 1095 Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5]; 1096 Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d]; 1097 Trajectories[walker].R.at(MDSteps).x[d] += delta_t*(Trajectories[walker].U.at(MDSteps-1).x[d]); 1098 Trajectories[walker].R.at(MDSteps).x[d] += 0.5*delta_t*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d])/IonMass; // F = m * a and s = 0.5 * F/m * t^2 = F * a * t 1099 } 1100 // 2. Calculate v(t+\delta t) 1101 for (int d=0; d<NDIM; d++) { 1102 Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d]; 1103 Trajectories[walker].U.at(MDSteps).x[d] += 0.5*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d]+Trajectories[walker].F.at(MDSteps).x[d])/IonMass; 1104 } 1105 // cout << "Integrated position&velocity of step " << (MDSteps) << ": ("; 1106 // for (int d=0;d<NDIM;d++) 1107 // cout << Trajectories[walker].R.at(MDSteps).x[d] << " "; // next step 1108 // cout << ")\t("; 1109 // for (int d=0;d<NDIM;d++) 1110 // cout << Trajectories[walker].U.at(MDSteps).x[d] << " "; // next step 1111 // cout << ")" << endl; 1112 // next atom 1113 AtomNo++; 1114 } 1115 } 1116 } 1117 } 1118 } 1119 // // correct velocities (rather momenta) so that center of mass remains motionless 1120 // tmpvector.zero() 1121 // IonMass = 0.; 1122 // walker = start; 1123 // while (walker->next != end) { // go through every atom 1124 // walker = walker->next; 1125 // IonMass += walker->type->mass; // sum up total mass 1126 // for(int d=0;d<NDIM;d++) { 1127 // tmpvector.x[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass; 1128 // } 1129 // } 1130 // walker = start; 1131 // while (walker->next != end) { // go through every atom of this element 1132 // walker = walker->next; 1133 // for(int d=0;d<NDIM;d++) { 1134 // Trajectories[walker].U.at(MDSteps).x[d] -= tmpvector.x[d]*walker->type->mass/IonMass; 1135 // } 1136 // } 1137 MDSteps++; 1138 1139 1140 // exit 1141 return true; 1142 1142 }; 1143 1143 … … 1147 1147 void molecule::Align(Vector *n) 1148 1148 { 1149 atom *ptr = start;1150 double alpha, tmp;1151 Vector z_axis;1152 z_axis.x[0] = 0.;1153 z_axis.x[1] = 0.;1154 z_axis.x[2] = 1.;1155 1156 // rotate on z-x plane1157 cout << Verbose(0) << "Begin of Aligning all atoms." << endl;1158 alpha = atan(-n->x[0]/n->x[2]);1159 cout << Verbose(1) << "Z-X-angle: " << alpha << " ... ";1160 while (ptr->next != end) {1161 ptr = ptr->next;1162 tmp = ptr->x.x[0];1163 ptr->x.x[0] =cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];1164 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];1165 for (int j=0;j<MDSteps;j++) {1166 tmp = Trajectories[ptr].R.at(j).x[0];1167 Trajectories[ptr].R.at(j).x[0] =cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];1168 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2];1169 }1170 }1171 // rotate n vector1172 tmp = n->x[0];1173 n->x[0] = cos(alpha) * tmp +sin(alpha) * n->x[2];1174 n->x[2] = -sin(alpha) * tmp +cos(alpha) * n->x[2];1175 cout << Verbose(1) << "alignment vector after first rotation: ";1176 n->Output((ofstream *)&cout);1177 cout << endl;1178 1179 // rotate on z-y plane1180 ptr = start;1181 alpha = atan(-n->x[1]/n->x[2]);1182 cout << Verbose(1) << "Z-Y-angle: " << alpha << " ... ";1183 while (ptr->next != end) {1184 ptr = ptr->next;1185 tmp = ptr->x.x[1];1186 ptr->x.x[1] =cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];1187 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];1188 for (int j=0;j<MDSteps;j++) {1189 tmp = Trajectories[ptr].R.at(j).x[1];1190 Trajectories[ptr].R.at(j).x[1] =cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];1191 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2];1192 }1193 }1194 // rotate n vector (for consistency check)1195 tmp = n->x[1];1196 n->x[1] = cos(alpha) * tmp +sin(alpha) * n->x[2];1197 n->x[2] = -sin(alpha) * tmp +cos(alpha) * n->x[2];1198 1199 cout << Verbose(1) << "alignment vector after second rotation: ";1200 n->Output((ofstream *)&cout);1201 cout << Verbose(1) << endl;1202 cout << Verbose(0) << "End of Aligning all atoms." << endl;1149 atom *ptr = start; 1150 double alpha, tmp; 1151 Vector z_axis; 1152 z_axis.x[0] = 0.; 1153 z_axis.x[1] = 0.; 1154 z_axis.x[2] = 1.; 1155 1156 // rotate on z-x plane 1157 cout << Verbose(0) << "Begin of Aligning all atoms." << endl; 1158 alpha = atan(-n->x[0]/n->x[2]); 1159 cout << Verbose(1) << "Z-X-angle: " << alpha << " ... "; 1160 while (ptr->next != end) { 1161 ptr = ptr->next; 1162 tmp = ptr->x.x[0]; 1163 ptr->x.x[0] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1164 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1165 for (int j=0;j<MDSteps;j++) { 1166 tmp = Trajectories[ptr].R.at(j).x[0]; 1167 Trajectories[ptr].R.at(j).x[0] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1168 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1169 } 1170 } 1171 // rotate n vector 1172 tmp = n->x[0]; 1173 n->x[0] = cos(alpha) * tmp + sin(alpha) * n->x[2]; 1174 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2]; 1175 cout << Verbose(1) << "alignment vector after first rotation: "; 1176 n->Output((ofstream *)&cout); 1177 cout << endl; 1178 1179 // rotate on z-y plane 1180 ptr = start; 1181 alpha = atan(-n->x[1]/n->x[2]); 1182 cout << Verbose(1) << "Z-Y-angle: " << alpha << " ... "; 1183 while (ptr->next != end) { 1184 ptr = ptr->next; 1185 tmp = ptr->x.x[1]; 1186 ptr->x.x[1] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1187 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1188 for (int j=0;j<MDSteps;j++) { 1189 tmp = Trajectories[ptr].R.at(j).x[1]; 1190 Trajectories[ptr].R.at(j).x[1] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1191 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1192 } 1193 } 1194 // rotate n vector (for consistency check) 1195 tmp = n->x[1]; 1196 n->x[1] = cos(alpha) * tmp + sin(alpha) * n->x[2]; 1197 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2]; 1198 1199 cout << Verbose(1) << "alignment vector after second rotation: "; 1200 n->Output((ofstream *)&cout); 1201 cout << Verbose(1) << endl; 1202 cout << Verbose(0) << "End of Aligning all atoms." << endl; 1203 1203 }; 1204 1204 … … 1209 1209 bool molecule::RemoveAtom(atom *pointer) 1210 1210 { 1211 if (ElementsInMolecule[pointer->type->Z] != 0){ // this would indicate an error1212 ElementsInMolecule[pointer->type->Z]--;// decrease number of atom of this element1213 AtomCount--;1214 } else1215 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl;1216 if (ElementsInMolecule[pointer->type->Z] == 0)// was last atom of this element?1217 ElementCount--;1218 Trajectories.erase(pointer);1219 return remove(pointer, start, end);1211 if (ElementsInMolecule[pointer->type->Z] != 0) { // this would indicate an error 1212 ElementsInMolecule[pointer->type->Z]--; // decrease number of atom of this element 1213 AtomCount--; 1214 } else 1215 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl; 1216 if (ElementsInMolecule[pointer->type->Z] == 0) // was last atom of this element? 1217 ElementCount--; 1218 Trajectories.erase(pointer); 1219 return remove(pointer, start, end); 1220 1220 }; 1221 1221 … … 1244 1244 bool molecule::CleanupMolecule() 1245 1245 { 1246 return (cleanup(start,end) && cleanup(first,last));1246 return (cleanup(start,end) && cleanup(first,last)); 1247 1247 }; 1248 1248 … … 1251 1251 * \return pointer to atom or NULL 1252 1252 */ 1253 atom * molecule::FindAtom(int Nr) const{1254 atom * walker = find(&Nr, start,end);1255 if (walker != NULL) {1256 //cout << Verbose(0) << "Found Atom Nr. " << walker->nr << endl;1257 return walker;1258 } else {1259 cout << Verbose(0) << "Atom not found in list." << endl;1260 return NULL;1261 }1253 atom * molecule::FindAtom(int Nr) const{ 1254 atom * walker = find(&Nr, start,end); 1255 if (walker != NULL) { 1256 //cout << Verbose(0) << "Found Atom Nr. " << walker->nr << endl; 1257 return walker; 1258 } else { 1259 cout << Verbose(0) << "Atom not found in list." << endl; 1260 return NULL; 1261 } 1262 1262 }; 1263 1263 … … 1267 1267 atom * molecule::AskAtom(string text) 1268 1268 { 1269 int No;1270 atom *ion = NULL;1271 do {1272 //cout << Verbose(0) << "============Atom list==========================" << endl;1273 //mol->Output((ofstream *)&cout);1274 //cout << Verbose(0) << "===============================================" << endl;1275 cout << Verbose(0) << text;1276 cin >> No;1277 ion = this->FindAtom(No);1278 } while (ion == NULL);1279 return ion;1269 int No; 1270 atom *ion = NULL; 1271 do { 1272 //cout << Verbose(0) << "============Atom list==========================" << endl; 1273 //mol->Output((ofstream *)&cout); 1274 //cout << Verbose(0) << "===============================================" << endl; 1275 cout << Verbose(0) << text; 1276 cin >> No; 1277 ion = this->FindAtom(No); 1278 } while (ion == NULL); 1279 return ion; 1280 1280 }; 1281 1281 … … 1286 1286 bool molecule::CheckBounds(const Vector *x) const 1287 1287 { 1288 bool result = true;1289 int j =-1;1290 for (int i=0;i<NDIM;i++) {1291 j += i+1;1292 result = result && ((x->x[i] >= 0) && (x->x[i] < cell_size[j]));1293 }1294 //return result;1295 return true; /// probably not gonna use the check no more1288 bool result = true; 1289 int j =-1; 1290 for (int i=0;i<NDIM;i++) { 1291 j += i+1; 1292 result = result && ((x->x[i] >= 0) && (x->x[i] < cell_size[j])); 1293 } 1294 //return result; 1295 return true; /// probably not gonna use the check no more 1296 1296 }; 1297 1297 … … 1303 1303 double LeastSquareDistance (const gsl_vector * x, void * params) 1304 1304 { 1305 double res = 0, t;1306 Vector a,b,c,d;1307 struct lsq_params *par = (struct lsq_params *)params;1308 atom *ptr = par->mol->start;1309 1310 // initialize vectors1311 a.x[0] = gsl_vector_get(x,0);1312 a.x[1] = gsl_vector_get(x,1);1313 a.x[2] = gsl_vector_get(x,2);1314 b.x[0] = gsl_vector_get(x,3);1315 b.x[1] = gsl_vector_get(x,4);1316 b.x[2] = gsl_vector_get(x,5);1317 // go through all atoms1318 while (ptr != par->mol->end) {1319 ptr = ptr->next;1320 if (ptr->type == ((struct lsq_params *)params)->type) { // for specific type1321 c.CopyVector(&ptr->x);// copy vector to temporary one1322 c.SubtractVector(&a);// subtract offset vector1323 t = c.ScalarProduct(&b);// get direction parameter1324 d.CopyVector(&b);// and create vector1325 d.Scale(&t);1326 c.SubtractVector(&d);// ... yielding distance vector1327 res += d.ScalarProduct((const Vector *)&d);// add squared distance1328 }1329 }1330 return res;1305 double res = 0, t; 1306 Vector a,b,c,d; 1307 struct lsq_params *par = (struct lsq_params *)params; 1308 atom *ptr = par->mol->start; 1309 1310 // initialize vectors 1311 a.x[0] = gsl_vector_get(x,0); 1312 a.x[1] = gsl_vector_get(x,1); 1313 a.x[2] = gsl_vector_get(x,2); 1314 b.x[0] = gsl_vector_get(x,3); 1315 b.x[1] = gsl_vector_get(x,4); 1316 b.x[2] = gsl_vector_get(x,5); 1317 // go through all atoms 1318 while (ptr != par->mol->end) { 1319 ptr = ptr->next; 1320 if (ptr->type == ((struct lsq_params *)params)->type) { // for specific type 1321 c.CopyVector(&ptr->x); // copy vector to temporary one 1322 c.SubtractVector(&a); // subtract offset vector 1323 t = c.ScalarProduct(&b); // get direction parameter 1324 d.CopyVector(&b); // and create vector 1325 d.Scale(&t); 1326 c.SubtractVector(&d); // ... yielding distance vector 1327 res += d.ScalarProduct((const Vector *)&d); // add squared distance 1328 } 1329 } 1330 return res; 1331 1331 }; 1332 1332 … … 1336 1336 void molecule::GetAlignvector(struct lsq_params * par) const 1337 1337 { 1338 int np = 6;1339 1340 const gsl_multimin_fminimizer_type *T =1341 gsl_multimin_fminimizer_nmsimplex;1342 gsl_multimin_fminimizer *s = NULL;1343 gsl_vector *ss;1344 gsl_multimin_function minex_func;1345 1346 size_t iter = 0, i;1347 int status;1348 double size;1349 1350 /* Initial vertex size vector */1351 ss = gsl_vector_alloc (np);1352 1353 /* Set all step sizes to 1 */1354 gsl_vector_set_all (ss, 1.0);1355 1356 /* Starting point */1357 par->x = gsl_vector_alloc (np);1358 par->mol = this;1359 1360 gsl_vector_set (par->x, 0, 0.0);// offset1361 gsl_vector_set (par->x, 1, 0.0);1362 gsl_vector_set (par->x, 2, 0.0);1363 gsl_vector_set (par->x, 3, 0.0);// direction1364 gsl_vector_set (par->x, 4, 0.0);1365 gsl_vector_set (par->x, 5, 1.0);1366 1367 /* Initialize method and iterate */1368 minex_func.f = &LeastSquareDistance;1369 minex_func.n = np;1370 minex_func.params = (void *)par;1371 1372 s = gsl_multimin_fminimizer_alloc (T, np);1373 gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss);1374 1375 do1376 {1377 iter++;1378 status = gsl_multimin_fminimizer_iterate(s);1379 1380 if (status)1381 break;1382 1383 size = gsl_multimin_fminimizer_size (s);1384 status = gsl_multimin_test_size (size, 1e-2);1385 1386 if (status == GSL_SUCCESS)1387 {1388 printf ("converged to minimum at\n");1389 }1390 1391 printf ("%5d ", (int)iter);1392 for (i = 0; i < (size_t)np; i++)1393 {1394 printf ("%10.3e ", gsl_vector_get (s->x, i));1395 }1396 printf ("f() = %7.3f size = %.3f\n", s->fval, size);1397 }1398 while (status == GSL_CONTINUE && iter < 100);1399 1400 for (i=0;i<(size_t)np;i++)1401 gsl_vector_set(par->x, i, gsl_vector_get(s->x, i));1402 //gsl_vector_free(par->x);1403 gsl_vector_free(ss);1404 gsl_multimin_fminimizer_free (s);1338 int np = 6; 1339 1340 const gsl_multimin_fminimizer_type *T = 1341 gsl_multimin_fminimizer_nmsimplex; 1342 gsl_multimin_fminimizer *s = NULL; 1343 gsl_vector *ss; 1344 gsl_multimin_function minex_func; 1345 1346 size_t iter = 0, i; 1347 int status; 1348 double size; 1349 1350 /* Initial vertex size vector */ 1351 ss = gsl_vector_alloc (np); 1352 1353 /* Set all step sizes to 1 */ 1354 gsl_vector_set_all (ss, 1.0); 1355 1356 /* Starting point */ 1357 par->x = gsl_vector_alloc (np); 1358 par->mol = this; 1359 1360 gsl_vector_set (par->x, 0, 0.0); // offset 1361 gsl_vector_set (par->x, 1, 0.0); 1362 gsl_vector_set (par->x, 2, 0.0); 1363 gsl_vector_set (par->x, 3, 0.0); // direction 1364 gsl_vector_set (par->x, 4, 0.0); 1365 gsl_vector_set (par->x, 5, 1.0); 1366 1367 /* Initialize method and iterate */ 1368 minex_func.f = &LeastSquareDistance; 1369 minex_func.n = np; 1370 minex_func.params = (void *)par; 1371 1372 s = gsl_multimin_fminimizer_alloc (T, np); 1373 gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss); 1374 1375 do 1376 { 1377 iter++; 1378 status = gsl_multimin_fminimizer_iterate(s); 1379 1380 if (status) 1381 break; 1382 1383 size = gsl_multimin_fminimizer_size (s); 1384 status = gsl_multimin_test_size (size, 1e-2); 1385 1386 if (status == GSL_SUCCESS) 1387 { 1388 printf ("converged to minimum at\n"); 1389 } 1390 1391 printf ("%5d ", (int)iter); 1392 for (i = 0; i < (size_t)np; i++) 1393 { 1394 printf ("%10.3e ", gsl_vector_get (s->x, i)); 1395 } 1396 printf ("f() = %7.3f size = %.3f\n", s->fval, size); 1397 } 1398 while (status == GSL_CONTINUE && iter < 100); 1399 1400 for (i=0;i<(size_t)np;i++) 1401 gsl_vector_set(par->x, i, gsl_vector_get(s->x, i)); 1402 //gsl_vector_free(par->x); 1403 gsl_vector_free(ss); 1404 gsl_multimin_fminimizer_free (s); 1405 1405 }; 1406 1406 … … 1410 1410 bool molecule::Output(ofstream *out) 1411 1411 { 1412 element *runner;1413 atom *walker = NULL;1414 int ElementNo, AtomNo;1415 CountElements();1416 1417 if (out == NULL) {1418 return false;1419 } else {1420 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2]MoveType (0 MoveIon, 1 FixedIon)" << endl;1421 ElementNo = 0;1422 runner = elemente->start;1423 while (runner->next != elemente->end) { // go through every element1424 runner = runner->next;1425 if (ElementsInMolecule[runner->Z]) { // if this element got atoms1426 ElementNo++;1427 AtomNo = 0;1428 walker = start;1429 while (walker->next != end) { // go through every atom of this element1430 walker = walker->next;1431 if (walker->type == runner) { // if this atom fits to element1432 AtomNo++;1433 walker->Output(ElementNo, AtomNo, out); // removed due to trajectories1434 }1435 }1436 }1437 }1438 return true;1439 }1412 element *runner; 1413 atom *walker = NULL; 1414 int ElementNo, AtomNo; 1415 CountElements(); 1416 1417 if (out == NULL) { 1418 return false; 1419 } else { 1420 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2] MoveType (0 MoveIon, 1 FixedIon)" << endl; 1421 ElementNo = 0; 1422 runner = elemente->start; 1423 while (runner->next != elemente->end) { // go through every element 1424 runner = runner->next; 1425 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1426 ElementNo++; 1427 AtomNo = 0; 1428 walker = start; 1429 while (walker->next != end) { // go through every atom of this element 1430 walker = walker->next; 1431 if (walker->type == runner) { // if this atom fits to element 1432 AtomNo++; 1433 walker->Output(ElementNo, AtomNo, out); // removed due to trajectories 1434 } 1435 } 1436 } 1437 } 1438 return true; 1439 } 1440 1440 }; 1441 1441 … … 1445 1445 bool molecule::OutputTrajectories(ofstream *out) 1446 1446 { 1447 element *runner = NULL;1448 atom *walker = NULL;1449 int ElementNo, AtomNo;1450 CountElements();1451 1452 if (out == NULL) {1453 return false;1454 } else {1455 for (int step = 0; step < MDSteps; step++) {1456 if (step == 0) {1457 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2]MoveType (0 MoveIon, 1 FixedIon)" << endl;1458 } else {1459 *out << "# ====== MD step " << step << " =========" << endl;1460 }1461 ElementNo = 0;1462 runner = elemente->start;1463 while (runner->next != elemente->end) { // go through every element1464 runner = runner->next;1465 if (ElementsInMolecule[runner->Z]) { // if this element got atoms1466 ElementNo++;1467 AtomNo = 0;1468 walker = start;1469 while (walker->next != end) { // go through every atom of this element1470 walker = walker->next;1471 if (walker->type == runner) { // if this atom fits to element1472 AtomNo++;1473 *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t"<< fixed << setprecision(9) << showpoint;1474 *out << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2];1475 *out << "\t" << walker->FixedIon;1476 if (Trajectories[walker].U.at(step).Norm() > MYEPSILON)1477 *out << "\t" << scientific << setprecision(6) << Trajectories[walker].U.at(step).x[0] << "\t" << Trajectories[walker].U.at(step).x[1] << "\t" << Trajectories[walker].U.at(step).x[2] << "\t";1478 if (Trajectories[walker].F.at(step).Norm() > MYEPSILON)1479 *out << "\t" << scientific << setprecision(6) << Trajectories[walker].F.at(step).x[0] << "\t" << Trajectories[walker].F.at(step).x[1] << "\t" << Trajectories[walker].F.at(step).x[2] << "\t";1480 *out << "\t# Number in molecule " << walker->nr << endl;1481 }1482 }1483 }1484 }1485 }1486 return true;1487 }1447 element *runner = NULL; 1448 atom *walker = NULL; 1449 int ElementNo, AtomNo; 1450 CountElements(); 1451 1452 if (out == NULL) { 1453 return false; 1454 } else { 1455 for (int step = 0; step < MDSteps; step++) { 1456 if (step == 0) { 1457 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2] MoveType (0 MoveIon, 1 FixedIon)" << endl; 1458 } else { 1459 *out << "# ====== MD step " << step << " =========" << endl; 1460 } 1461 ElementNo = 0; 1462 runner = elemente->start; 1463 while (runner->next != elemente->end) { // go through every element 1464 runner = runner->next; 1465 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1466 ElementNo++; 1467 AtomNo = 0; 1468 walker = start; 1469 while (walker->next != end) { // go through every atom of this element 1470 walker = walker->next; 1471 if (walker->type == runner) { // if this atom fits to element 1472 AtomNo++; 1473 *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t" << fixed << setprecision(9) << showpoint; 1474 *out << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2]; 1475 *out << "\t" << walker->FixedIon; 1476 if (Trajectories[walker].U.at(step).Norm() > MYEPSILON) 1477 *out << "\t" << scientific << setprecision(6) << Trajectories[walker].U.at(step).x[0] << "\t" << Trajectories[walker].U.at(step).x[1] << "\t" << Trajectories[walker].U.at(step).x[2] << "\t"; 1478 if (Trajectories[walker].F.at(step).Norm() > MYEPSILON) 1479 *out << "\t" << scientific << setprecision(6) << Trajectories[walker].F.at(step).x[0] << "\t" << Trajectories[walker].F.at(step).x[1] << "\t" << Trajectories[walker].F.at(step).x[2] << "\t"; 1480 *out << "\t# Number in molecule " << walker->nr << endl; 1481 } 1482 } 1483 } 1484 } 1485 } 1486 return true; 1487 } 1488 1488 }; 1489 1489 … … 1493 1493 void molecule::OutputListOfBonds(ofstream *out) const 1494 1494 { 1495 *out << Verbose(2) << endl << "From Contents of ListOfBondsPerAtom, all non-hydrogen atoms:" << endl;1496 atom *Walker = start;1497 while (Walker->next != end) {1498 Walker = Walker->next;1495 *out << Verbose(2) << endl << "From Contents of ListOfBondsPerAtom, all non-hydrogen atoms:" << endl; 1496 atom *Walker = start; 1497 while (Walker->next != end) { 1498 Walker = Walker->next; 1499 1499 #ifdef ADDHYDROGEN 1500 if (Walker->type->Z != 1) {// regard only non-hydrogen1500 if (Walker->type->Z != 1) { // regard only non-hydrogen 1501 1501 #endif 1502 *out << Verbose(2) << "Atom " << Walker->Name << " has Bonds: "<<endl;1503 for(int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) {1504 *out << Verbose(3) << *(ListOfBondsPerAtom)[Walker->nr][j] << endl;1505 }1502 *out << Verbose(2) << "Atom " << Walker->Name << " has Bonds: "<<endl; 1503 for(int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) { 1504 *out << Verbose(3) << *(ListOfBondsPerAtom)[Walker->nr][j] << endl; 1505 } 1506 1506 #ifdef ADDHYDROGEN 1507 }1507 } 1508 1508 #endif 1509 }1510 *out << endl;1509 } 1510 *out << endl; 1511 1511 }; 1512 1512 … … 1514 1514 * \param *out stream pointer 1515 1515 */ 1516 bool molecule::Checkout(ofstream *out) const1517 { 1518 return elemente->Checkout(out, ElementsInMolecule);1516 bool molecule::Checkout(ofstream *out) const 1517 { 1518 return elemente->Checkout(out, ElementsInMolecule); 1519 1519 }; 1520 1520 … … 1524 1524 bool molecule::OutputTrajectoriesXYZ(ofstream *out) 1525 1525 { 1526 atom *walker = NULL;1527 int No = 0;1528 time_t now;1529 1530 now = time((time_t *)NULL);// Get the system time and put it into 'now' as 'calender time'1531 walker = start;1532 while (walker->next != end) { // go through every atom and count1533 walker = walker->next;1534 No++;1535 }1536 if (out != NULL) {1537 for (int step=0;step<MDSteps;step++) {1538 *out << No << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now);1539 walker = start;1540 while (walker->next != end) { // go through every atom of this element1541 walker = walker->next;1542 *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;1543 }1544 }1545 return true;1546 } else1547 return false;1526 atom *walker = NULL; 1527 int No = 0; 1528 time_t now; 1529 1530 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 1531 walker = start; 1532 while (walker->next != end) { // go through every atom and count 1533 walker = walker->next; 1534 No++; 1535 } 1536 if (out != NULL) { 1537 for (int step=0;step<MDSteps;step++) { 1538 *out << No << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now); 1539 walker = start; 1540 while (walker->next != end) { // go through every atom of this element 1541 walker = walker->next; 1542 *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; 1543 } 1544 } 1545 return true; 1546 } else 1547 return false; 1548 1548 }; 1549 1549 … … 1553 1553 bool molecule::OutputXYZ(ofstream *out) const 1554 1554 { 1555 atom *walker = NULL;1556 int AtomNo = 0, ElementNo;1557 time_t now;1558 element *runner = NULL;1559 1560 now = time((time_t *)NULL);// Get the system time and put it into 'now' as 'calender time'1561 walker = start;1562 while (walker->next != end) { // go through every atom and count1563 walker = walker->next;1564 AtomNo++;1565 }1566 if (out != NULL) {1567 *out << AtomNo << "\n\tCreated by molecuilder on " << ctime(&now);1568 ElementNo = 0;1569 runner = elemente->start;1570 while (runner->next != elemente->end) { // go through every element1571 runner = runner->next;1572 if (ElementsInMolecule[runner->Z]) { // if this element got atoms1573 ElementNo++;1574 walker = start;1575 while (walker->next != end) { // go through every atom of this element1576 walker = walker->next;1577 if (walker->type == runner) { // if this atom fits to element1578 walker->OutputXYZLine(out);1579 }1580 }1581 }1582 }1583 return true;1584 } else1585 return false;1555 atom *walker = NULL; 1556 int AtomNo = 0, ElementNo; 1557 time_t now; 1558 element *runner = NULL; 1559 1560 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 1561 walker = start; 1562 while (walker->next != end) { // go through every atom and count 1563 walker = walker->next; 1564 AtomNo++; 1565 } 1566 if (out != NULL) { 1567 *out << AtomNo << "\n\tCreated by molecuilder on " << ctime(&now); 1568 ElementNo = 0; 1569 runner = elemente->start; 1570 while (runner->next != elemente->end) { // go through every element 1571 runner = runner->next; 1572 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1573 ElementNo++; 1574 walker = start; 1575 while (walker->next != end) { // go through every atom of this element 1576 walker = walker->next; 1577 if (walker->type == runner) { // if this atom fits to element 1578 walker->OutputXYZLine(out); 1579 } 1580 } 1581 } 1582 } 1583 return true; 1584 } else 1585 return false; 1586 1586 }; 1587 1587 … … 1591 1591 void molecule::CountAtoms(ofstream *out) 1592 1592 { 1593 int i = 0;1594 atom *Walker = start;1595 while (Walker->next != end) {1596 Walker = Walker->next;1597 i++;1598 }1599 if ((AtomCount == 0) || (i != AtomCount)) {1600 *out << Verbose(3) << "Mismatch in AtomCount " << AtomCount << " and recounted number " << i << ", renaming all." << endl;1601 AtomCount = i;1602 1603 // count NonHydrogen atoms and give each atom a unique name1604 if (AtomCount != 0) {1605 i=0;1606 NoNonHydrogen = 0;1607 Walker = start;1608 while (Walker->next != end) {1609 Walker = Walker->next;1610 Walker->nr = i;// update number in molecule (for easier referencing in FragmentMolecule lateron)1611 if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it1612 NoNonHydrogen++;1613 Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name");1614 Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name");1615 sprintf(Walker->Name, "%2s%02d", Walker->type->symbol, Walker->nr+1);1616 *out << "Naming atom nr. " << Walker->nr << " " << Walker->Name << "." << endl;1617 i++;1618 }1619 } else1620 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl;1621 }1593 int i = 0; 1594 atom *Walker = start; 1595 while (Walker->next != end) { 1596 Walker = Walker->next; 1597 i++; 1598 } 1599 if ((AtomCount == 0) || (i != AtomCount)) { 1600 *out << Verbose(3) << "Mismatch in AtomCount " << AtomCount << " and recounted number " << i << ", renaming all." << endl; 1601 AtomCount = i; 1602 1603 // count NonHydrogen atoms and give each atom a unique name 1604 if (AtomCount != 0) { 1605 i=0; 1606 NoNonHydrogen = 0; 1607 Walker = start; 1608 while (Walker->next != end) { 1609 Walker = Walker->next; 1610 Walker->nr = i; // update number in molecule (for easier referencing in FragmentMolecule lateron) 1611 if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it 1612 NoNonHydrogen++; 1613 Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name"); 1614 Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name"); 1615 sprintf(Walker->Name, "%2s%02d", Walker->type->symbol, Walker->nr+1); 1616 *out << "Naming atom nr. " << Walker->nr << " " << Walker->Name << "." << endl; 1617 i++; 1618 } 1619 } else 1620 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 1621 } 1622 1622 }; 1623 1623 … … 1626 1626 void molecule::CountElements() 1627 1627 { 1628 int i = 0;1629 for(i=MAX_ELEMENTS;i--;)1630 ElementsInMolecule[i] = 0;1631 ElementCount = 0;1632 1633 atom *walker = start;1634 while (walker->next != end) {1635 walker = walker->next;1636 ElementsInMolecule[walker->type->Z]++;1637 i++;1638 }1639 for(i=MAX_ELEMENTS;i--;)1640 ElementCount += (ElementsInMolecule[i] != 0 ? 1 : 0);1628 int i = 0; 1629 for(i=MAX_ELEMENTS;i--;) 1630 ElementsInMolecule[i] = 0; 1631 ElementCount = 0; 1632 1633 atom *walker = start; 1634 while (walker->next != end) { 1635 walker = walker->next; 1636 ElementsInMolecule[walker->type->Z]++; 1637 i++; 1638 } 1639 for(i=MAX_ELEMENTS;i--;) 1640 ElementCount += (ElementsInMolecule[i] != 0 ? 1 : 0); 1641 1641 }; 1642 1642 … … 1648 1648 int molecule::CountCyclicBonds(ofstream *out) 1649 1649 { 1650 int No = 0;1651 int *MinimumRingSize = NULL;1652 MoleculeLeafClass *Subgraphs = NULL;1653 class StackClass<bond *> *BackEdgeStack = NULL;1654 bond *Binder = first;1655 if ((Binder->next != last) && (Binder->next->Type == Undetermined)) {1656 *out << Verbose(0) << "No Depth-First-Search analysis performed so far, calling ..." << endl;1657 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack);1658 while (Subgraphs->next != NULL) {1659 Subgraphs = Subgraphs->next;1660 delete(Subgraphs->previous);1661 }1662 delete(Subgraphs);1663 delete[](MinimumRingSize);1664 }1665 while(Binder->next != last) {1666 Binder = Binder->next;1667 if (Binder->Cyclic)1668 No++;1669 }1670 delete(BackEdgeStack);1671 return No;1650 int No = 0; 1651 int *MinimumRingSize = NULL; 1652 MoleculeLeafClass *Subgraphs = NULL; 1653 class StackClass<bond *> *BackEdgeStack = NULL; 1654 bond *Binder = first; 1655 if ((Binder->next != last) && (Binder->next->Type == Undetermined)) { 1656 *out << Verbose(0) << "No Depth-First-Search analysis performed so far, calling ..." << endl; 1657 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack); 1658 while (Subgraphs->next != NULL) { 1659 Subgraphs = Subgraphs->next; 1660 delete(Subgraphs->previous); 1661 } 1662 delete(Subgraphs); 1663 delete[](MinimumRingSize); 1664 } 1665 while(Binder->next != last) { 1666 Binder = Binder->next; 1667 if (Binder->Cyclic) 1668 No++; 1669 } 1670 delete(BackEdgeStack); 1671 return No; 1672 1672 }; 1673 1673 /** Returns Shading as a char string. … … 1677 1677 string molecule::GetColor(enum Shading color) 1678 1678 { 1679 switch(color) {1680 case white:1681 return "white";1682 break;1683 case lightgray:1684 return "lightgray";1685 break;1686 case darkgray:1687 return "darkgray";1688 break;1689 case black:1690 return "black";1691 break;1692 default:1693 return "uncolored";1694 break;1695 };1679 switch(color) { 1680 case white: 1681 return "white"; 1682 break; 1683 case lightgray: 1684 return "lightgray"; 1685 break; 1686 case darkgray: 1687 return "darkgray"; 1688 break; 1689 case black: 1690 return "black"; 1691 break; 1692 default: 1693 return "uncolored"; 1694 break; 1695 }; 1696 1696 }; 1697 1697 … … 1702 1702 void molecule::CalculateOrbitals(class config &configuration) 1703 1703 { 1704 configuration.MaxPsiDouble = configuration.PsiMaxNoDown = configuration.PsiMaxNoUp = configuration.PsiType = 0;1705 for(int i=MAX_ELEMENTS;i--;) {1706 if (ElementsInMolecule[i] != 0) {1707 //cout << "CalculateOrbitals: " << elemente->FindElement(i)->name << " has a valence of " << (int)elemente->FindElement(i)->Valence << " and there are " << ElementsInMolecule[i] << " of it." << endl;1708 configuration.MaxPsiDouble += ElementsInMolecule[i]*((int)elemente->FindElement(i)->Valence);1709 }1710 }1711 configuration.PsiMaxNoDown = configuration.MaxPsiDouble/2 + (configuration.MaxPsiDouble % 2);1712 configuration.PsiMaxNoUp = configuration.MaxPsiDouble/2;1713 configuration.MaxPsiDouble /= 2;1714 configuration.PsiType = (configuration.PsiMaxNoDown == configuration.PsiMaxNoUp) ? 0 : 1;1715 if ((configuration.PsiType == 1) && (configuration.ProcPEPsi < 2)) {1716 configuration.ProcPEGamma /= 2;1717 configuration.ProcPEPsi *= 2;1718 } else {1719 configuration.ProcPEGamma *= configuration.ProcPEPsi;1720 configuration.ProcPEPsi = 1;1721 }1722 configuration.InitMaxMinStopStep = configuration.MaxMinStopStep = configuration.MaxPsiDouble;1704 configuration.MaxPsiDouble = configuration.PsiMaxNoDown = configuration.PsiMaxNoUp = configuration.PsiType = 0; 1705 for(int i=MAX_ELEMENTS;i--;) { 1706 if (ElementsInMolecule[i] != 0) { 1707 //cout << "CalculateOrbitals: " << elemente->FindElement(i)->name << " has a valence of " << (int)elemente->FindElement(i)->Valence << " and there are " << ElementsInMolecule[i] << " of it." << endl; 1708 configuration.MaxPsiDouble += ElementsInMolecule[i]*((int)elemente->FindElement(i)->Valence); 1709 } 1710 } 1711 configuration.PsiMaxNoDown = configuration.MaxPsiDouble/2 + (configuration.MaxPsiDouble % 2); 1712 configuration.PsiMaxNoUp = configuration.MaxPsiDouble/2; 1713 configuration.MaxPsiDouble /= 2; 1714 configuration.PsiType = (configuration.PsiMaxNoDown == configuration.PsiMaxNoUp) ? 0 : 1; 1715 if ((configuration.PsiType == 1) && (configuration.ProcPEPsi < 2)) { 1716 configuration.ProcPEGamma /= 2; 1717 configuration.ProcPEPsi *= 2; 1718 } else { 1719 configuration.ProcPEGamma *= configuration.ProcPEPsi; 1720 configuration.ProcPEPsi = 1; 1721 } 1722 configuration.InitMaxMinStopStep = configuration.MaxMinStopStep = configuration.MaxPsiDouble; 1723 1723 }; 1724 1724 … … 1729 1729 { 1730 1730 1731 // 1 We will parse bonds out of the dbond file created by tremolo.1732 int atom1, atom2, temp;1733 atom *Walker, *OtherWalker;1734 1735 if (!input)1736 {1737 cout << Verbose(1) << "Opening silica failed \n";1738 };1739 1740 *input >> ws >> atom1;1741 *input >> ws >> atom2;1742 cout << Verbose(1) << "Scanning file\n";1743 while (!input->eof()) // Check whether we read everything already1744 {1745 *input >> ws >> atom1;1746 *input >> ws >> atom2;1747 if(atom2<atom1) //Sort indices of atoms in order1748 {1749 temp=atom1;1750 atom1=atom2;1751 atom2=temp;1752 };1753 1754 Walker=start;1755 while(Walker-> nr != atom1) // Find atom corresponding to first index1756 {1757 Walker = Walker->next;1758 };1759 OtherWalker = Walker->next;1760 while(OtherWalker->nr != atom2) // Find atom corresponding to second index1761 {1762 OtherWalker= OtherWalker->next;1763 };1764 AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices.1765 1766 }1767 1768 CreateListOfBondsPerAtom(out);1731 // 1 We will parse bonds out of the dbond file created by tremolo. 1732 int atom1, atom2, temp; 1733 atom *Walker, *OtherWalker; 1734 1735 if (!input) 1736 { 1737 cout << Verbose(1) << "Opening silica failed \n"; 1738 }; 1739 1740 *input >> ws >> atom1; 1741 *input >> ws >> atom2; 1742 cout << Verbose(1) << "Scanning file\n"; 1743 while (!input->eof()) // Check whether we read everything already 1744 { 1745 *input >> ws >> atom1; 1746 *input >> ws >> atom2; 1747 if(atom2<atom1) //Sort indices of atoms in order 1748 { 1749 temp=atom1; 1750 atom1=atom2; 1751 atom2=temp; 1752 }; 1753 1754 Walker=start; 1755 while(Walker-> nr != atom1) // Find atom corresponding to first index 1756 { 1757 Walker = Walker->next; 1758 }; 1759 OtherWalker = Walker->next; 1760 while(OtherWalker->nr != atom2) // Find atom corresponding to second index 1761 { 1762 OtherWalker= OtherWalker->next; 1763 }; 1764 AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices. 1765 1766 } 1767 1768 CreateListOfBondsPerAtom(out); 1769 1769 1770 1770 }; … … 1777 1777 * To make it O(N log N) the function uses the linked-cell technique as follows: 1778 1778 * The procedure is step-wise: 1779 * -# Remove every bond in list1780 * -# Count the atoms in the molecule with CountAtoms()1781 * -# partition cell into smaller linked cells of size \a bonddistance1782 * -# put each atom into its corresponding cell1783 * -# go through every cell, check the atoms therein against all possible bond partners in the 27 adjacent cells, add bond if true1784 * -# create the list of bonds via CreateListOfBondsPerAtom()1785 * -# correct the bond degree iteratively (single->double->triple bond)1786 * -# finally print the bond list to \a *out if desired1779 * -# Remove every bond in list 1780 * -# Count the atoms in the molecule with CountAtoms() 1781 * -# partition cell into smaller linked cells of size \a bonddistance 1782 * -# put each atom into its corresponding cell 1783 * -# go through every cell, check the atoms therein against all possible bond partners in the 27 adjacent cells, add bond if true 1784 * -# create the list of bonds via CreateListOfBondsPerAtom() 1785 * -# correct the bond degree iteratively (single->double->triple bond) 1786 * -# finally print the bond list to \a *out if desired 1787 1787 * \param *out out stream for printing the matrix, NULL if no output 1788 1788 * \param bonddistance length of linked cells (i.e. maximum minimal length checked) … … 1792 1792 { 1793 1793 1794 atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL;1795 int No, NoBonds, CandidateBondNo;1796 int NumberCells, divisor[NDIM], n[NDIM], N[NDIM], index, Index, j;1797 molecule **CellList;1798 double distance, MinDistance, MaxDistance;1799 double *matrix = ReturnFullMatrixforSymmetric(cell_size);1800 Vector x;1801 int FalseBondDegree = 0;1802 1803 BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem);1804 *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl;1805 // remove every bond from the list1806 if ((first->next != last) && (last->previous != first)) {// there are bonds present1807 cleanup(first,last);1808 }1809 1810 // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering)1811 CountAtoms(out);1812 *out << Verbose(1) << "AtomCount " << AtomCount << "." << endl;1813 1814 if (AtomCount != 0) {1815 // 1. find divisor for each axis, such that a sphere with radius of at least bonddistance can be placed into each cell1816 j=-1;1817 for (int i=0;i<NDIM;i++) {1818 j += i+1;1819 divisor[i] = (int)floor(cell_size[j]/bonddistance); // take smaller value such that size of linked cell is at least bonddistance1820 //*out << Verbose(1) << "divisor[" << i << "]= " << divisor[i] << "." << endl;1821 }1822 // 2a. allocate memory for the cell list1823 NumberCells = divisor[0]*divisor[1]*divisor[2];1824 *out << Verbose(1) << "Allocating " << NumberCells << " cells." << endl;1825 CellList = (molecule **) Malloc(sizeof(molecule *)*NumberCells, "molecule::CreateAdjacencyList - ** CellList");1826 for (int i=NumberCells;i--;)1827 CellList[i] = NULL;1828 1829 // 2b. put all atoms into its corresponding list1830 Walker = start;1831 while(Walker->next != end) {1832 Walker = Walker->next;1833 //*out << Verbose(1) << "Current atom is " << *Walker << " with coordinates ";1834 //Walker->x.Output(out);1835 //*out << "." << endl;1836 // compute the cell by the atom's coordinates1837 j=-1;1838 for (int i=0;i<NDIM;i++) {1839 j += i+1;1840 x.CopyVector(&(Walker->x));1841 x.KeepPeriodic(out, matrix);1842 n[i] = (int)floor(x.x[i]/cell_size[j]*(double)divisor[i]);1843 }1844 index = n[2] + (n[1] + n[0] * divisor[1]) * divisor[2];1845 //*out << Verbose(1) << "Atom " << *Walker << " goes into cell number [" << n[0] << "," << n[1] << "," << n[2] << "] = " << index << "." << endl;1846 // add copy atom to this cell1847 if (CellList[index] == NULL)// allocate molecule if not done1848 CellList[index] = new molecule(elemente);1849 OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference1850 //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl;1851 }1852 //for (int i=0;i<NumberCells;i++)1853 //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl;1854 1855 1856 // 3a. go through every cell1857 for (N[0]=divisor[0];N[0]--;)1858 for (N[1]=divisor[1];N[1]--;)1859 for (N[2]=divisor[2];N[2]--;) {1860 Index = N[2] + (N[1] + N[0] * divisor[1]) * divisor[2];1861 if (CellList[Index] != NULL) { // if there atoms in this cell1862 //*out << Verbose(1) << "Current cell is " << Index << "." << endl;1863 // 3b. for every atom therein1864 Walker = CellList[Index]->start;1865 while (Walker->next != CellList[Index]->end) {// go through every atom1866 Walker = Walker->next;1867 //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl;1868 // 3c. check for possible bond between each atom in this and every one in the 27 cells1869 for (n[0]=-1;n[0]<=1;n[0]++)1870 for (n[1]=-1;n[1]<=1;n[1]++)1871 for (n[2]=-1;n[2]<=1;n[2]++) {1872 // compute the index of this comparison cell and make it periodic1873 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];1874 //*out << Verbose(1) << "Number of comparison cell is " << index << "." << endl;1875 if (CellList[index] != NULL) {// if there are any atoms in this cell1876 OtherWalker = CellList[index]->start;1877 while(OtherWalker->next != CellList[index]->end) {// go through every atom in this cell1878 OtherWalker = OtherWalker->next;1879 //*out << Verbose(0) << "Current comparison atom is " << *OtherWalker << "." << endl;1880 /// \todo periodic check is missing here!1881 //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl;1882 MinDistance = OtherWalker->type->CovalentRadius + Walker->type->CovalentRadius;1883 MinDistance *= (IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem;1884 MaxDistance = MinDistance + BONDTHRESHOLD;1885 MinDistance -= BONDTHRESHOLD;1886 distance = OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size);1887 if ((OtherWalker->father->nr > Walker->father->nr) && (distance <= MaxDistance*MaxDistance) && (distance >= MinDistance*MinDistance)) { // create bond if distance is smaller1888 //*out << Verbose(1) << "Adding Bond between " << *Walker << " and " << *OtherWalker << " in distance " << sqrt(distance) << "." << endl;1889 AddBond(Walker->father, OtherWalker->father, 1);// also increases molecule::BondCount1890 } else {1891 //*out << Verbose(1) << "Not Adding: Wrong label order or distance too great." << endl;1892 }1893 }1894 }1895 }1896 }1897 }1898 }1899 1900 1901 1902 // 4. free the cell again1903 for (int i=NumberCells;i--;)1904 if (CellList[i] != NULL) {1905 delete(CellList[i]);1906 }1907 Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList");1908 1909 // create the adjacency list per atom1910 CreateListOfBondsPerAtom(out);1911 1912 // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees,1913 // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene1914 // preferred over carbon bonds). Beforehand, we had picked the first mismatching partner, which lead to oxygenes with single instead of1915 // double bonds as was expected.1916 if (BondCount != 0) {1917 NoCyclicBonds = 0;1918 *out << Verbose(1) << "Correcting Bond degree of each bond ... ";1919 do {1920 No = 0; // No acts as breakup flag (if 1 we still continue)1921 Walker = start;1922 while (Walker->next != end) { // go through every atom1923 Walker = Walker->next;1924 // count valence of first partner1925 NoBonds = 0;1926 for(j=0;j<NumberOfBondsPerAtom[Walker->nr];j++)1927 NoBonds += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;1928 *out << Verbose(3) << "Walker " << *Walker << ": " << (int)Walker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;1929 if ((int)(Walker->type->NoValenceOrbitals) > NoBonds) { // we have a mismatch, check all bonding partners for mismatch1930 Candidate = NULL;1931 CandidateBondNo = -1;1932 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through each of its bond partners1933 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);1934 // count valence of second partner1935 NoBonds = 0;1936 for(j=0;j<NumberOfBondsPerAtom[OtherWalker->nr];j++)1937 NoBonds += ListOfBondsPerAtom[OtherWalker->nr][j]->BondDegree;1938 *out << Verbose(3) << "OtherWalker " << *OtherWalker << ": " << (int)OtherWalker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;1939 if ((int)(OtherWalker->type->NoValenceOrbitals) > NoBonds) { // check if possible candidate1940 if ((Candidate == NULL) || (NumberOfBondsPerAtom[Candidate->nr] > NumberOfBondsPerAtom[OtherWalker->nr])) { // pick the one with fewer number of bonds first1941 Candidate = OtherWalker;1942 CandidateBondNo = i;1943 *out << Verbose(3) << "New candidate is " << *Candidate << "." << endl;1944 }1945 }1946 }1947 if ((Candidate != NULL) && (CandidateBondNo != -1)) {1948 ListOfBondsPerAtom[Walker->nr][CandidateBondNo]->BondDegree++;1949 *out << Verbose(2) << "Increased bond degree for bond " << *ListOfBondsPerAtom[Walker->nr][CandidateBondNo] << "." << endl;1950 } else1951 *out << Verbose(2) << "Could not find correct degree for atom " << *Walker << "." << endl;1952 FalseBondDegree++;1953 }1954 }1955 } while (No);1956 *out << " done." << endl;1957 } else1958 *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl;1959 *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl;1960 1961 // output bonds for debugging (if bond chain list was correctly installed)1962 *out << Verbose(1) << endl << "From contents of bond chain list:";1963 bond *Binder = first;1964 while(Binder->next != last) {1965 Binder = Binder->next;1966 *out << *Binder << "\t" << endl;1967 }1968 *out << endl;1969 } else1970 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl;1971 *out << Verbose(0) << "End of CreateAdjacencyList." << endl;1972 Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix");1794 atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL; 1795 int No, NoBonds, CandidateBondNo; 1796 int NumberCells, divisor[NDIM], n[NDIM], N[NDIM], index, Index, j; 1797 molecule **CellList; 1798 double distance, MinDistance, MaxDistance; 1799 double *matrix = ReturnFullMatrixforSymmetric(cell_size); 1800 Vector x; 1801 int FalseBondDegree = 0; 1802 1803 BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem); 1804 *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl; 1805 // remove every bond from the list 1806 if ((first->next != last) && (last->previous != first)) { // there are bonds present 1807 cleanup(first,last); 1808 } 1809 1810 // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering) 1811 CountAtoms(out); 1812 *out << Verbose(1) << "AtomCount " << AtomCount << "." << endl; 1813 1814 if (AtomCount != 0) { 1815 // 1. find divisor for each axis, such that a sphere with radius of at least bonddistance can be placed into each cell 1816 j=-1; 1817 for (int i=0;i<NDIM;i++) { 1818 j += i+1; 1819 divisor[i] = (int)floor(cell_size[j]/bonddistance); // take smaller value such that size of linked cell is at least bonddistance 1820 //*out << Verbose(1) << "divisor[" << i << "] = " << divisor[i] << "." << endl; 1821 } 1822 // 2a. allocate memory for the cell list 1823 NumberCells = divisor[0]*divisor[1]*divisor[2]; 1824 *out << Verbose(1) << "Allocating " << NumberCells << " cells." << endl; 1825 CellList = (molecule **) Malloc(sizeof(molecule *)*NumberCells, "molecule::CreateAdjacencyList - ** CellList"); 1826 for (int i=NumberCells;i--;) 1827 CellList[i] = NULL; 1828 1829 // 2b. put all atoms into its corresponding list 1830 Walker = start; 1831 while(Walker->next != end) { 1832 Walker = Walker->next; 1833 //*out << Verbose(1) << "Current atom is " << *Walker << " with coordinates "; 1834 //Walker->x.Output(out); 1835 //*out << "." << endl; 1836 // compute the cell by the atom's coordinates 1837 j=-1; 1838 for (int i=0;i<NDIM;i++) { 1839 j += i+1; 1840 x.CopyVector(&(Walker->x)); 1841 x.KeepPeriodic(out, matrix); 1842 n[i] = (int)floor(x.x[i]/cell_size[j]*(double)divisor[i]); 1843 } 1844 index = n[2] + (n[1] + n[0] * divisor[1]) * divisor[2]; 1845 //*out << Verbose(1) << "Atom " << *Walker << " goes into cell number [" << n[0] << "," << n[1] << "," << n[2] << "] = " << index << "." << endl; 1846 // add copy atom to this cell 1847 if (CellList[index] == NULL) // allocate molecule if not done 1848 CellList[index] = new molecule(elemente); 1849 OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference 1850 //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl; 1851 } 1852 //for (int i=0;i<NumberCells;i++) 1853 //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl; 1854 1855 1856 // 3a. go through every cell 1857 for (N[0]=divisor[0];N[0]--;) 1858 for (N[1]=divisor[1];N[1]--;) 1859 for (N[2]=divisor[2];N[2]--;) { 1860 Index = N[2] + (N[1] + N[0] * divisor[1]) * divisor[2]; 1861 if (CellList[Index] != NULL) { // if there atoms in this cell 1862 //*out << Verbose(1) << "Current cell is " << Index << "." << endl; 1863 // 3b. for every atom therein 1864 Walker = CellList[Index]->start; 1865 while (Walker->next != CellList[Index]->end) { // go through every atom 1866 Walker = Walker->next; 1867 //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl; 1868 // 3c. check for possible bond between each atom in this and every one in the 27 cells 1869 for (n[0]=-1;n[0]<=1;n[0]++) 1870 for (n[1]=-1;n[1]<=1;n[1]++) 1871 for (n[2]=-1;n[2]<=1;n[2]++) { 1872 // compute the index of this comparison cell and make it periodic 1873 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]; 1874 //*out << Verbose(1) << "Number of comparison cell is " << index << "." << endl; 1875 if (CellList[index] != NULL) { // if there are any atoms in this cell 1876 OtherWalker = CellList[index]->start; 1877 while(OtherWalker->next != CellList[index]->end) { // go through every atom in this cell 1878 OtherWalker = OtherWalker->next; 1879 //*out << Verbose(0) << "Current comparison atom is " << *OtherWalker << "." << endl; 1880 /// \todo periodic check is missing here! 1881 //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl; 1882 MinDistance = OtherWalker->type->CovalentRadius + Walker->type->CovalentRadius; 1883 MinDistance *= (IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem; 1884 MaxDistance = MinDistance + BONDTHRESHOLD; 1885 MinDistance -= BONDTHRESHOLD; 1886 distance = OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size); 1887 if ((OtherWalker->father->nr > Walker->father->nr) && (distance <= MaxDistance*MaxDistance) && (distance >= MinDistance*MinDistance)) { // create bond if distance is smaller 1888 //*out << Verbose(1) << "Adding Bond between " << *Walker << " and " << *OtherWalker << " in distance " << sqrt(distance) << "." << endl; 1889 AddBond(Walker->father, OtherWalker->father, 1); // also increases molecule::BondCount 1890 } else { 1891 //*out << Verbose(1) << "Not Adding: Wrong label order or distance too great." << endl; 1892 } 1893 } 1894 } 1895 } 1896 } 1897 } 1898 } 1899 1900 1901 1902 // 4. free the cell again 1903 for (int i=NumberCells;i--;) 1904 if (CellList[i] != NULL) { 1905 delete(CellList[i]); 1906 } 1907 Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList"); 1908 1909 // create the adjacency list per atom 1910 CreateListOfBondsPerAtom(out); 1911 1912 // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees, 1913 // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene 1914 // preferred over carbon bonds). Beforehand, we had picked the first mismatching partner, which lead to oxygenes with single instead of 1915 // double bonds as was expected. 1916 if (BondCount != 0) { 1917 NoCyclicBonds = 0; 1918 *out << Verbose(1) << "Correcting Bond degree of each bond ... "; 1919 do { 1920 No = 0; // No acts as breakup flag (if 1 we still continue) 1921 Walker = start; 1922 while (Walker->next != end) { // go through every atom 1923 Walker = Walker->next; 1924 // count valence of first partner 1925 NoBonds = 0; 1926 for(j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) 1927 NoBonds += ListOfBondsPerAtom[Walker->nr][j]->BondDegree; 1928 *out << Verbose(3) << "Walker " << *Walker << ": " << (int)Walker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl; 1929 if ((int)(Walker->type->NoValenceOrbitals) > NoBonds) { // we have a mismatch, check all bonding partners for mismatch 1930 Candidate = NULL; 1931 CandidateBondNo = -1; 1932 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through each of its bond partners 1933 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 1934 // count valence of second partner 1935 NoBonds = 0; 1936 for(j=0;j<NumberOfBondsPerAtom[OtherWalker->nr];j++) 1937 NoBonds += ListOfBondsPerAtom[OtherWalker->nr][j]->BondDegree; 1938 *out << Verbose(3) << "OtherWalker " << *OtherWalker << ": " << (int)OtherWalker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl; 1939 if ((int)(OtherWalker->type->NoValenceOrbitals) > NoBonds) { // check if possible candidate 1940 if ((Candidate == NULL) || (NumberOfBondsPerAtom[Candidate->nr] > NumberOfBondsPerAtom[OtherWalker->nr])) { // pick the one with fewer number of bonds first 1941 Candidate = OtherWalker; 1942 CandidateBondNo = i; 1943 *out << Verbose(3) << "New candidate is " << *Candidate << "." << endl; 1944 } 1945 } 1946 } 1947 if ((Candidate != NULL) && (CandidateBondNo != -1)) { 1948 ListOfBondsPerAtom[Walker->nr][CandidateBondNo]->BondDegree++; 1949 *out << Verbose(2) << "Increased bond degree for bond " << *ListOfBondsPerAtom[Walker->nr][CandidateBondNo] << "." << endl; 1950 } else 1951 *out << Verbose(2) << "Could not find correct degree for atom " << *Walker << "." << endl; 1952 FalseBondDegree++; 1953 } 1954 } 1955 } while (No); 1956 *out << " done." << endl; 1957 } else 1958 *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl; 1959 *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl; 1960 1961 // output bonds for debugging (if bond chain list was correctly installed) 1962 *out << Verbose(1) << endl << "From contents of bond chain list:"; 1963 bond *Binder = first; 1964 while(Binder->next != last) { 1965 Binder = Binder->next; 1966 *out << *Binder << "\t" << endl; 1967 } 1968 *out << endl; 1969 } else 1970 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl; 1971 *out << Verbose(0) << "End of CreateAdjacencyList." << endl; 1972 Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix"); 1973 1973 1974 1974 }; … … 1986 1986 MoleculeLeafClass * molecule::DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack) 1987 1987 { 1988 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);1989 BackEdgeStack = new StackClass<bond *> (BondCount);1990 MoleculeLeafClass *SubGraphs = new MoleculeLeafClass(NULL);1991 MoleculeLeafClass *LeafWalker = SubGraphs;1992 int CurrentGraphNr = 0, OldGraphNr;1993 int ComponentNumber = 0;1994 atom *Walker = NULL, *OtherAtom = NULL, *Root = start->next;1995 bond *Binder = NULL;1996 bool BackStepping = false;1997 1998 *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl;1999 2000 ResetAllBondsToUnused();2001 ResetAllAtomNumbers();2002 InitComponentNumbers();2003 BackEdgeStack->ClearStack();2004 while (Root != end) { // if there any atoms at all2005 // (1) mark all edges unused, empty stack, set atom->GraphNr = 0 for all2006 AtomStack->ClearStack();2007 2008 // put into new subgraph molecule and add this to list of subgraphs2009 LeafWalker = new MoleculeLeafClass(LeafWalker);2010 LeafWalker->Leaf = new molecule(elemente);2011 LeafWalker->Leaf->AddCopyAtom(Root);2012 2013 OldGraphNr = CurrentGraphNr;2014 Walker = Root;2015 do { // (10)2016 do { // (2) set number and Lowpoint of Atom to i, increase i, push current atom2017 if (!BackStepping) { // if we don't just return from (8)2018 Walker->GraphNr = CurrentGraphNr;2019 Walker->LowpointNr = CurrentGraphNr;2020 *out << Verbose(1) << "Setting Walker[" << Walker->Name << "]'s number to " << Walker->GraphNr << " with Lowpoint " << Walker->LowpointNr << "." << endl;2021 AtomStack->Push(Walker);2022 CurrentGraphNr++;2023 }2024 do { // (3) if Walker has no unused egdes, go to (5)2025 BackStepping = false; // reset backstepping flag for (8)2026 if (Binder == NULL) // if we don't just return from (11), Binder is already set to next unused2027 Binder = FindNextUnused(Walker);2028 if (Binder == NULL)2029 break;2030 *out << Verbose(2) << "Current Unused Bond is " << *Binder << "." << endl;2031 // (4) Mark Binder used, ...2032 Binder->MarkUsed(black);2033 OtherAtom = Binder->GetOtherAtom(Walker);2034 *out << Verbose(2) << "(4) OtherAtom is " << OtherAtom->Name << "." << endl;2035 if (OtherAtom->GraphNr != -1) {2036 // (4a) ... if "other" atom has been visited (GraphNr != 0), set lowpoint to minimum of both, go to (3)2037 Binder->Type = BackEdge;2038 BackEdgeStack->Push(Binder);2039 Walker->LowpointNr = ( Walker->LowpointNr < OtherAtom->GraphNr ) ? Walker->LowpointNr : OtherAtom->GraphNr;2040 *out << Verbose(3) << "(4a) Visited: Setting Lowpoint of Walker[" << Walker->Name << "] to " << Walker->LowpointNr << "." << endl;2041 } else {2042 // (4b) ... otherwise set OtherAtom as Ancestor of Walker and Walker as OtherAtom, go to (2)2043 Binder->Type = TreeEdge;2044 OtherAtom->Ancestor = Walker;2045 Walker = OtherAtom;2046 *out << Verbose(3) << "(4b) Not Visited: OtherAtom[" << OtherAtom->Name << "]'s Ancestor is now " << OtherAtom->Ancestor->Name << ", Walker is OtherAtom " << OtherAtom->Name << "." << endl;2047 break;2048 }2049 Binder = NULL;2050 } while (1);// (3)2051 if (Binder == NULL) {2052 *out << Verbose(2) << "No more Unused Bonds." << endl;2053 break;2054 } else2055 Binder = NULL;2056 } while (1);// (2)2057 2058 // 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!2059 if ((Walker == Root) && (Binder == NULL))2060 break;2061 2062 // (5) if Ancestor of Walker is ...2063 *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl;2064 if (Walker->Ancestor->GraphNr != Root->GraphNr) {2065 // (6)(Ancestor of Walker is not Root)2066 if (Walker->LowpointNr < Walker->Ancestor->GraphNr) {2067 // (6a) set Ancestor's Lowpoint number to minimum of of its Ancestor and itself, go to Step(8)2068 Walker->Ancestor->LowpointNr = (Walker->Ancestor->LowpointNr < Walker->LowpointNr) ? Walker->Ancestor->LowpointNr : Walker->LowpointNr;2069 *out << Verbose(2) << "(6) Setting Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s Lowpoint to " << Walker->Ancestor->LowpointNr << "." << endl;2070 } else {2071 // (7) (Ancestor of Walker is a separating vertex, remove all from stack till Walker (including), these and Ancestor form a component2072 Walker->Ancestor->SeparationVertex = true;2073 *out << Verbose(2) << "(7) Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s is a separating vertex, creating component." << endl;2074 SetNextComponentNumber(Walker->Ancestor, ComponentNumber);2075 *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Ancestor's Compont is " << ComponentNumber << "." << endl;2076 SetNextComponentNumber(Walker, ComponentNumber);2077 *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Compont is " << ComponentNumber << "." << endl;2078 do {2079 OtherAtom = AtomStack->PopLast();2080 LeafWalker->Leaf->AddCopyAtom(OtherAtom);2081 SetNextComponentNumber(OtherAtom, ComponentNumber);2082 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;2083 } while (OtherAtom != Walker);2084 ComponentNumber++;2085 }2086 // (8) Walker becomes its Ancestor, go to (3)2087 *out << Verbose(2) << "(8) Walker[" << Walker->Name << "] is now its Ancestor " << Walker->Ancestor->Name << ", backstepping. " << endl;2088 Walker = Walker->Ancestor;2089 BackStepping = true;2090 }2091 if (!BackStepping) {// coming from (8) want to go to (3)2092 // (9) remove all from stack till Walker (including), these and Root form a component2093 AtomStack->Output(out);2094 SetNextComponentNumber(Root, ComponentNumber);2095 *out << Verbose(3) << "(9) Root[" << Root->Name << "]'s Component is " << ComponentNumber << "." << endl;2096 SetNextComponentNumber(Walker, ComponentNumber);2097 *out << Verbose(3) << "(9) Walker[" << Walker->Name << "]'s Component is " << ComponentNumber << "." << endl;2098 do {2099 OtherAtom = AtomStack->PopLast();2100 LeafWalker->Leaf->AddCopyAtom(OtherAtom);2101 SetNextComponentNumber(OtherAtom, ComponentNumber);2102 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;2103 } while (OtherAtom != Walker);2104 ComponentNumber++;2105 2106 // (11) Root is separation vertex,set Walker to Root and go to (4)2107 Walker = Root;2108 Binder = FindNextUnused(Walker);2109 *out << Verbose(1) << "(10) Walker is Root[" << Root->Name << "], next Unused Bond is " << Binder << "." << endl;2110 if (Binder != NULL) { // Root is separation vertex2111 *out << Verbose(1) << "(11) Root is a separation vertex." << endl;2112 Walker->SeparationVertex = true;2113 }2114 }2115 } while ((BackStepping) || (Binder != NULL)); // (10) halt only if Root has no unused edges2116 2117 // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph2118 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl;2119 LeafWalker->Leaf->Output(out);2120 *out << endl;2121 2122 // step on to next root2123 while ((Root != end) && (Root->GraphNr != -1)) {2124 //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl;2125 if (Root->GraphNr != -1) // if already discovered, step on2126 Root = Root->next;2127 }2128 }2129 // set cyclic bond criterium on "same LP" basis2130 Binder = first;2131 while(Binder->next != last) {2132 Binder = Binder->next;2133 if (Binder->rightatom->LowpointNr == Binder->leftatom->LowpointNr) { // cyclic ??2134 Binder->Cyclic = true;2135 NoCyclicBonds++;2136 }2137 }2138 2139 2140 *out << Verbose(1) << "Final graph info for each atom is:" << endl;2141 Walker = start;2142 while (Walker->next != end) {2143 Walker = Walker->next;2144 *out << Verbose(2) << "Atom " << Walker->Name << " is " << ((Walker->SeparationVertex) ? "a" : "not a") << " separation vertex, components are ";2145 OutputComponentNumber(out, Walker);2146 *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl;2147 }2148 2149 *out << Verbose(1) << "Final graph info for each bond is:" << endl;2150 Binder = first;2151 while(Binder->next != last) {2152 Binder = Binder->next;2153 *out << Verbose(2) << ((Binder->Type == TreeEdge) ? "TreeEdge " : "BackEdge ") << *Binder << ": <";2154 *out << ((Binder->leftatom->SeparationVertex) ? "SP," : "") << "L" << Binder->leftatom->LowpointNr << " G" << Binder->leftatom->GraphNr << " Comp.";2155 OutputComponentNumber(out, Binder->leftatom);2156 *out << " ===";2157 *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp.";2158 OutputComponentNumber(out, Binder->rightatom);2159 *out << ">." << endl;2160 if (Binder->Cyclic) // cyclic ??2161 *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl;2162 }2163 2164 // free all and exit2165 delete(AtomStack);2166 *out << Verbose(0) << "End of DepthFirstSearchAnalysis" << endl;2167 return SubGraphs;1988 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount); 1989 BackEdgeStack = new StackClass<bond *> (BondCount); 1990 MoleculeLeafClass *SubGraphs = new MoleculeLeafClass(NULL); 1991 MoleculeLeafClass *LeafWalker = SubGraphs; 1992 int CurrentGraphNr = 0, OldGraphNr; 1993 int ComponentNumber = 0; 1994 atom *Walker = NULL, *OtherAtom = NULL, *Root = start->next; 1995 bond *Binder = NULL; 1996 bool BackStepping = false; 1997 1998 *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl; 1999 2000 ResetAllBondsToUnused(); 2001 ResetAllAtomNumbers(); 2002 InitComponentNumbers(); 2003 BackEdgeStack->ClearStack(); 2004 while (Root != end) { // if there any atoms at all 2005 // (1) mark all edges unused, empty stack, set atom->GraphNr = 0 for all 2006 AtomStack->ClearStack(); 2007 2008 // put into new subgraph molecule and add this to list of subgraphs 2009 LeafWalker = new MoleculeLeafClass(LeafWalker); 2010 LeafWalker->Leaf = new molecule(elemente); 2011 LeafWalker->Leaf->AddCopyAtom(Root); 2012 2013 OldGraphNr = CurrentGraphNr; 2014 Walker = Root; 2015 do { // (10) 2016 do { // (2) set number and Lowpoint of Atom to i, increase i, push current atom 2017 if (!BackStepping) { // if we don't just return from (8) 2018 Walker->GraphNr = CurrentGraphNr; 2019 Walker->LowpointNr = CurrentGraphNr; 2020 *out << Verbose(1) << "Setting Walker[" << Walker->Name << "]'s number to " << Walker->GraphNr << " with Lowpoint " << Walker->LowpointNr << "." << endl; 2021 AtomStack->Push(Walker); 2022 CurrentGraphNr++; 2023 } 2024 do { // (3) if Walker has no unused egdes, go to (5) 2025 BackStepping = false; // reset backstepping flag for (8) 2026 if (Binder == NULL) // if we don't just return from (11), Binder is already set to next unused 2027 Binder = FindNextUnused(Walker); 2028 if (Binder == NULL) 2029 break; 2030 *out << Verbose(2) << "Current Unused Bond is " << *Binder << "." << endl; 2031 // (4) Mark Binder used, ... 2032 Binder->MarkUsed(black); 2033 OtherAtom = Binder->GetOtherAtom(Walker); 2034 *out << Verbose(2) << "(4) OtherAtom is " << OtherAtom->Name << "." << endl; 2035 if (OtherAtom->GraphNr != -1) { 2036 // (4a) ... if "other" atom has been visited (GraphNr != 0), set lowpoint to minimum of both, go to (3) 2037 Binder->Type = BackEdge; 2038 BackEdgeStack->Push(Binder); 2039 Walker->LowpointNr = ( Walker->LowpointNr < OtherAtom->GraphNr ) ? Walker->LowpointNr : OtherAtom->GraphNr; 2040 *out << Verbose(3) << "(4a) Visited: Setting Lowpoint of Walker[" << Walker->Name << "] to " << Walker->LowpointNr << "." << endl; 2041 } else { 2042 // (4b) ... otherwise set OtherAtom as Ancestor of Walker and Walker as OtherAtom, go to (2) 2043 Binder->Type = TreeEdge; 2044 OtherAtom->Ancestor = Walker; 2045 Walker = OtherAtom; 2046 *out << Verbose(3) << "(4b) Not Visited: OtherAtom[" << OtherAtom->Name << "]'s Ancestor is now " << OtherAtom->Ancestor->Name << ", Walker is OtherAtom " << OtherAtom->Name << "." << endl; 2047 break; 2048 } 2049 Binder = NULL; 2050 } while (1); // (3) 2051 if (Binder == NULL) { 2052 *out << Verbose(2) << "No more Unused Bonds." << endl; 2053 break; 2054 } else 2055 Binder = NULL; 2056 } while (1); // (2) 2057 2058 // 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! 2059 if ((Walker == Root) && (Binder == NULL)) 2060 break; 2061 2062 // (5) if Ancestor of Walker is ... 2063 *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl; 2064 if (Walker->Ancestor->GraphNr != Root->GraphNr) { 2065 // (6) (Ancestor of Walker is not Root) 2066 if (Walker->LowpointNr < Walker->Ancestor->GraphNr) { 2067 // (6a) set Ancestor's Lowpoint number to minimum of of its Ancestor and itself, go to Step(8) 2068 Walker->Ancestor->LowpointNr = (Walker->Ancestor->LowpointNr < Walker->LowpointNr) ? Walker->Ancestor->LowpointNr : Walker->LowpointNr; 2069 *out << Verbose(2) << "(6) Setting Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s Lowpoint to " << Walker->Ancestor->LowpointNr << "." << endl; 2070 } else { 2071 // (7) (Ancestor of Walker is a separating vertex, remove all from stack till Walker (including), these and Ancestor form a component 2072 Walker->Ancestor->SeparationVertex = true; 2073 *out << Verbose(2) << "(7) Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s is a separating vertex, creating component." << endl; 2074 SetNextComponentNumber(Walker->Ancestor, ComponentNumber); 2075 *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Ancestor's Compont is " << ComponentNumber << "." << endl; 2076 SetNextComponentNumber(Walker, ComponentNumber); 2077 *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Compont is " << ComponentNumber << "." << endl; 2078 do { 2079 OtherAtom = AtomStack->PopLast(); 2080 LeafWalker->Leaf->AddCopyAtom(OtherAtom); 2081 SetNextComponentNumber(OtherAtom, ComponentNumber); 2082 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl; 2083 } while (OtherAtom != Walker); 2084 ComponentNumber++; 2085 } 2086 // (8) Walker becomes its Ancestor, go to (3) 2087 *out << Verbose(2) << "(8) Walker[" << Walker->Name << "] is now its Ancestor " << Walker->Ancestor->Name << ", backstepping. " << endl; 2088 Walker = Walker->Ancestor; 2089 BackStepping = true; 2090 } 2091 if (!BackStepping) { // coming from (8) want to go to (3) 2092 // (9) remove all from stack till Walker (including), these and Root form a component 2093 AtomStack->Output(out); 2094 SetNextComponentNumber(Root, ComponentNumber); 2095 *out << Verbose(3) << "(9) Root[" << Root->Name << "]'s Component is " << ComponentNumber << "." << endl; 2096 SetNextComponentNumber(Walker, ComponentNumber); 2097 *out << Verbose(3) << "(9) Walker[" << Walker->Name << "]'s Component is " << ComponentNumber << "." << endl; 2098 do { 2099 OtherAtom = AtomStack->PopLast(); 2100 LeafWalker->Leaf->AddCopyAtom(OtherAtom); 2101 SetNextComponentNumber(OtherAtom, ComponentNumber); 2102 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl; 2103 } while (OtherAtom != Walker); 2104 ComponentNumber++; 2105 2106 // (11) Root is separation vertex, set Walker to Root and go to (4) 2107 Walker = Root; 2108 Binder = FindNextUnused(Walker); 2109 *out << Verbose(1) << "(10) Walker is Root[" << Root->Name << "], next Unused Bond is " << Binder << "." << endl; 2110 if (Binder != NULL) { // Root is separation vertex 2111 *out << Verbose(1) << "(11) Root is a separation vertex." << endl; 2112 Walker->SeparationVertex = true; 2113 } 2114 } 2115 } while ((BackStepping) || (Binder != NULL)); // (10) halt only if Root has no unused edges 2116 2117 // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph 2118 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2119 LeafWalker->Leaf->Output(out); 2120 *out << endl; 2121 2122 // step on to next root 2123 while ((Root != end) && (Root->GraphNr != -1)) { 2124 //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl; 2125 if (Root->GraphNr != -1) // if already discovered, step on 2126 Root = Root->next; 2127 } 2128 } 2129 // set cyclic bond criterium on "same LP" basis 2130 Binder = first; 2131 while(Binder->next != last) { 2132 Binder = Binder->next; 2133 if (Binder->rightatom->LowpointNr == Binder->leftatom->LowpointNr) { // cyclic ?? 2134 Binder->Cyclic = true; 2135 NoCyclicBonds++; 2136 } 2137 } 2138 2139 2140 *out << Verbose(1) << "Final graph info for each atom is:" << endl; 2141 Walker = start; 2142 while (Walker->next != end) { 2143 Walker = Walker->next; 2144 *out << Verbose(2) << "Atom " << Walker->Name << " is " << ((Walker->SeparationVertex) ? "a" : "not a") << " separation vertex, components are "; 2145 OutputComponentNumber(out, Walker); 2146 *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl; 2147 } 2148 2149 *out << Verbose(1) << "Final graph info for each bond is:" << endl; 2150 Binder = first; 2151 while(Binder->next != last) { 2152 Binder = Binder->next; 2153 *out << Verbose(2) << ((Binder->Type == TreeEdge) ? "TreeEdge " : "BackEdge ") << *Binder << ": <"; 2154 *out << ((Binder->leftatom->SeparationVertex) ? "SP," : "") << "L" << Binder->leftatom->LowpointNr << " G" << Binder->leftatom->GraphNr << " Comp."; 2155 OutputComponentNumber(out, Binder->leftatom); 2156 *out << " === "; 2157 *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp."; 2158 OutputComponentNumber(out, Binder->rightatom); 2159 *out << ">." << endl; 2160 if (Binder->Cyclic) // cyclic ?? 2161 *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl; 2162 } 2163 2164 // free all and exit 2165 delete(AtomStack); 2166 *out << Verbose(0) << "End of DepthFirstSearchAnalysis" << endl; 2167 return SubGraphs; 2168 2168 }; 2169 2169 … … 2178 2178 * \todo BFS from the not-same-LP to find back to starting point of tributary cycle over more than one bond 2179 2179 */ 2180 void molecule::CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> * BackEdgeStack, int *&MinimumRingSize)2181 { 2182 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CyclicStructureAnalysis: **PredecessorList");2183 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList");2184 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList");2185 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount);// will hold the current ring2186 class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount);// contains all "touched" atoms (that need to be reset after BFS loop)2187 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL;2188 bond *Binder = NULL, *BackEdge = NULL;2189 int RingSize, NumCycles, MinRingSize = -1;2190 2191 // initialise each vertex as white with no predecessor, empty queue, color Root lightgray2192 for (int i=AtomCount;i--;) {2193 PredecessorList[i] = NULL;2194 ShortestPathList[i] = -1;2195 ColorList[i] = white;2196 }2197 2198 *out << Verbose(1) << "Back edge list - ";2199 BackEdgeStack->Output(out);2200 2201 *out << Verbose(1) << "Analysing cycles ... " << endl;2202 NumCycles = 0;2203 while (!BackEdgeStack->IsEmpty()) {2204 BackEdge = BackEdgeStack->PopFirst();2205 // this is the target2206 Root = BackEdge->leftatom;2207 // this is the source point2208 Walker = BackEdge->rightatom;2209 ShortestPathList[Walker->nr] = 0;2210 BFSStack->ClearStack();// start with empty BFS stack2211 BFSStack->Push(Walker);2212 TouchedStack->Push(Walker);2213 *out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;2214 OtherAtom = NULL;2215 do {// look for Root2216 Walker = BFSStack->PopFirst();2217 *out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;2218 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {2219 Binder = ListOfBondsPerAtom[Walker->nr][i];2220 if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder)2221 OtherAtom = Binder->GetOtherAtom(Walker);2180 void molecule::CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> * BackEdgeStack, int *&MinimumRingSize) 2181 { 2182 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CyclicStructureAnalysis: **PredecessorList"); 2183 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList"); 2184 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList"); 2185 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount); // will hold the current ring 2186 class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount); // contains all "touched" atoms (that need to be reset after BFS loop) 2187 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL; 2188 bond *Binder = NULL, *BackEdge = NULL; 2189 int RingSize, NumCycles, MinRingSize = -1; 2190 2191 // initialise each vertex as white with no predecessor, empty queue, color Root lightgray 2192 for (int i=AtomCount;i--;) { 2193 PredecessorList[i] = NULL; 2194 ShortestPathList[i] = -1; 2195 ColorList[i] = white; 2196 } 2197 2198 *out << Verbose(1) << "Back edge list - "; 2199 BackEdgeStack->Output(out); 2200 2201 *out << Verbose(1) << "Analysing cycles ... " << endl; 2202 NumCycles = 0; 2203 while (!BackEdgeStack->IsEmpty()) { 2204 BackEdge = BackEdgeStack->PopFirst(); 2205 // this is the target 2206 Root = BackEdge->leftatom; 2207 // this is the source point 2208 Walker = BackEdge->rightatom; 2209 ShortestPathList[Walker->nr] = 0; 2210 BFSStack->ClearStack(); // start with empty BFS stack 2211 BFSStack->Push(Walker); 2212 TouchedStack->Push(Walker); 2213 *out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl; 2214 OtherAtom = NULL; 2215 do { // look for Root 2216 Walker = BFSStack->PopFirst(); 2217 *out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl; 2218 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 2219 Binder = ListOfBondsPerAtom[Walker->nr][i]; 2220 if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder) 2221 OtherAtom = Binder->GetOtherAtom(Walker); 2222 2222 #ifdef ADDHYDROGEN 2223 if (OtherAtom->type->Z != 1) {2223 if (OtherAtom->type->Z != 1) { 2224 2224 #endif 2225 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;2226 if (ColorList[OtherAtom->nr] == white) {2227 TouchedStack->Push(OtherAtom);2228 ColorList[OtherAtom->nr] = lightgray;2229 PredecessorList[OtherAtom->nr] = Walker;// Walker is the predecessor2230 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;2231 *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;2232 //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance2233 *out << Verbose(3) << "Putting OtherAtom into queue." << endl;2234 BFSStack->Push(OtherAtom);2235 //}2236 } else {2237 *out << Verbose(3) << "Not Adding, has already been visited." << endl;2238 }2239 if (OtherAtom == Root)2240 break;2225 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 2226 if (ColorList[OtherAtom->nr] == white) { 2227 TouchedStack->Push(OtherAtom); 2228 ColorList[OtherAtom->nr] = lightgray; 2229 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 2230 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 2231 *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; 2232 //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance 2233 *out << Verbose(3) << "Putting OtherAtom into queue." << endl; 2234 BFSStack->Push(OtherAtom); 2235 //} 2236 } else { 2237 *out << Verbose(3) << "Not Adding, has already been visited." << endl; 2238 } 2239 if (OtherAtom == Root) 2240 break; 2241 2241 #ifdef ADDHYDROGEN 2242 } else {2243 *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl;2244 ColorList[OtherAtom->nr] = black;2245 }2242 } else { 2243 *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl; 2244 ColorList[OtherAtom->nr] = black; 2245 } 2246 2246 #endif 2247 } else {2248 *out << Verbose(2) << "Bond " << *Binder << " not Visiting, is the back edge." << endl;2249 }2250 }2251 ColorList[Walker->nr] = black;2252 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;2253 if (OtherAtom == Root) { // if we have found the root, check whether this cycle wasn't already found beforehand2254 // step through predecessor list2255 while (OtherAtom != BackEdge->rightatom) {2256 if (!OtherAtom->GetTrueFather()->IsCyclic)// if one bond in the loop is not marked as cyclic, we haven't found this cycle yet2257 break;2258 else2259 OtherAtom = PredecessorList[OtherAtom->nr];2260 }2261 if (OtherAtom == BackEdge->rightatom) { // if each atom in found cycle is cyclic, loop's been found before already2262 *out << Verbose(3) << "This cycle was already found before, skipping and removing seeker from search." << endl;\2263 do {2264 OtherAtom = TouchedStack->PopLast();2265 if (PredecessorList[OtherAtom->nr] == Walker) {2266 *out << Verbose(4) << "Removing " << *OtherAtom << " from lists and stacks." << endl;2267 PredecessorList[OtherAtom->nr] = NULL;2268 ShortestPathList[OtherAtom->nr] = -1;2269 ColorList[OtherAtom->nr] = white;2270 BFSStack->RemoveItem(OtherAtom);2271 }2272 } while ((!TouchedStack->IsEmpty()) && (PredecessorList[OtherAtom->nr] == NULL));2273 TouchedStack->Push(OtherAtom);// last was wrongly popped2274 OtherAtom = BackEdge->rightatom; // set to not Root2275 } else2276 OtherAtom = Root;2277 }2278 } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr])));2279 2280 if (OtherAtom == Root) {2281 // now climb back the predecessor list and thus find the cycle members2282 NumCycles++;2283 RingSize = 1;2284 Root->GetTrueFather()->IsCyclic = true;2285 *out << Verbose(1) << "Found ring contains: ";2286 Walker = Root;2287 while (Walker != BackEdge->rightatom) {2288 *out << Walker->Name << " <-> ";2289 Walker = PredecessorList[Walker->nr];2290 Walker->GetTrueFather()->IsCyclic = true;2291 RingSize++;2292 }2293 *out << Walker->Name << "with a length of " << RingSize << "." << endl << endl;2294 // walk through all and set MinimumRingSize2295 Walker = Root;2296 MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;2297 while (Walker != BackEdge->rightatom) {2298 Walker = PredecessorList[Walker->nr];2299 if (RingSize < MinimumRingSize[Walker->GetTrueFather()->nr])2300 MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;2301 }2302 if ((RingSize < MinRingSize) || (MinRingSize == -1))2303 MinRingSize = RingSize;2304 } else {2305 *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl;2306 }2307 2308 // now clean the lists2309 while (!TouchedStack->IsEmpty()){2310 Walker = TouchedStack->PopFirst();2311 PredecessorList[Walker->nr] = NULL;2312 ShortestPathList[Walker->nr] = -1;2313 ColorList[Walker->nr] = white;2314 }2315 }2316 if (MinRingSize != -1) {2317 // go over all atoms2318 Root = start;2319 while(Root->next != end) {2320 Root = Root->next;2321 2322 if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is2323 Walker = Root;2324 ShortestPathList[Walker->nr] = 0;2325 BFSStack->ClearStack();// start with empty BFS stack2326 BFSStack->Push(Walker);2327 TouchedStack->Push(Walker);2328 //*out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;2329 OtherAtom = Walker;2330 while (OtherAtom != NULL) {// look for Root2331 Walker = BFSStack->PopFirst();2332 //*out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;2333 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {2334 Binder = ListOfBondsPerAtom[Walker->nr][i];2335 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 check2336 OtherAtom = Binder->GetOtherAtom(Walker);2337 //*out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;2338 if (ColorList[OtherAtom->nr] == white) {2339 TouchedStack->Push(OtherAtom);2340 ColorList[OtherAtom->nr] = lightgray;2341 PredecessorList[OtherAtom->nr] = Walker;// Walker is the predecessor2342 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;2343 //*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;2344 if (OtherAtom->GetTrueFather()->IsCyclic) { // if the other atom is connected to a ring2345 MinimumRingSize[Root->GetTrueFather()->nr] = ShortestPathList[OtherAtom->nr]+MinimumRingSize[OtherAtom->GetTrueFather()->nr];2346 OtherAtom = NULL; //break;2347 break;2348 } else2349 BFSStack->Push(OtherAtom);2350 } else {2351 //*out << Verbose(3) << "Not Adding, has already been visited." << endl;2352 }2353 } else {2354 //*out << Verbose(3) << "Not Visiting, is a back edge." << endl;2355 }2356 }2357 ColorList[Walker->nr] = black;2358 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;2359 }2360 2361 // now clean the lists2362 while (!TouchedStack->IsEmpty()){2363 Walker = TouchedStack->PopFirst();2364 PredecessorList[Walker->nr] = NULL;2365 ShortestPathList[Walker->nr] = -1;2366 ColorList[Walker->nr] = white;2367 }2368 }2369 *out << Verbose(1) << "Minimum ring size of " << *Root << " is " << MinimumRingSize[Root->GetTrueFather()->nr] << "." << endl;2370 }2371 *out << Verbose(1) << "Minimum ring size is " << MinRingSize << ", over " << NumCycles << " cycles total." << endl;2372 } else2373 *out << Verbose(1) << "No rings were detected in the molecular structure." << endl;2374 2375 Free((void **)&PredecessorList, "molecule::CyclicStructureAnalysis: **PredecessorList");2376 Free((void **)&ShortestPathList, "molecule::CyclicStructureAnalysis: **ShortestPathList");2377 Free((void **)&ColorList, "molecule::CyclicStructureAnalysis: **ColorList");2378 delete(BFSStack);2247 } else { 2248 *out << Verbose(2) << "Bond " << *Binder << " not Visiting, is the back edge." << endl; 2249 } 2250 } 2251 ColorList[Walker->nr] = black; 2252 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2253 if (OtherAtom == Root) { // if we have found the root, check whether this cycle wasn't already found beforehand 2254 // step through predecessor list 2255 while (OtherAtom != BackEdge->rightatom) { 2256 if (!OtherAtom->GetTrueFather()->IsCyclic) // if one bond in the loop is not marked as cyclic, we haven't found this cycle yet 2257 break; 2258 else 2259 OtherAtom = PredecessorList[OtherAtom->nr]; 2260 } 2261 if (OtherAtom == BackEdge->rightatom) { // if each atom in found cycle is cyclic, loop's been found before already 2262 *out << Verbose(3) << "This cycle was already found before, skipping and removing seeker from search." << endl;\ 2263 do { 2264 OtherAtom = TouchedStack->PopLast(); 2265 if (PredecessorList[OtherAtom->nr] == Walker) { 2266 *out << Verbose(4) << "Removing " << *OtherAtom << " from lists and stacks." << endl; 2267 PredecessorList[OtherAtom->nr] = NULL; 2268 ShortestPathList[OtherAtom->nr] = -1; 2269 ColorList[OtherAtom->nr] = white; 2270 BFSStack->RemoveItem(OtherAtom); 2271 } 2272 } while ((!TouchedStack->IsEmpty()) && (PredecessorList[OtherAtom->nr] == NULL)); 2273 TouchedStack->Push(OtherAtom); // last was wrongly popped 2274 OtherAtom = BackEdge->rightatom; // set to not Root 2275 } else 2276 OtherAtom = Root; 2277 } 2278 } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]))); 2279 2280 if (OtherAtom == Root) { 2281 // now climb back the predecessor list and thus find the cycle members 2282 NumCycles++; 2283 RingSize = 1; 2284 Root->GetTrueFather()->IsCyclic = true; 2285 *out << Verbose(1) << "Found ring contains: "; 2286 Walker = Root; 2287 while (Walker != BackEdge->rightatom) { 2288 *out << Walker->Name << " <-> "; 2289 Walker = PredecessorList[Walker->nr]; 2290 Walker->GetTrueFather()->IsCyclic = true; 2291 RingSize++; 2292 } 2293 *out << Walker->Name << " with a length of " << RingSize << "." << endl << endl; 2294 // walk through all and set MinimumRingSize 2295 Walker = Root; 2296 MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize; 2297 while (Walker != BackEdge->rightatom) { 2298 Walker = PredecessorList[Walker->nr]; 2299 if (RingSize < MinimumRingSize[Walker->GetTrueFather()->nr]) 2300 MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize; 2301 } 2302 if ((RingSize < MinRingSize) || (MinRingSize == -1)) 2303 MinRingSize = RingSize; 2304 } else { 2305 *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl; 2306 } 2307 2308 // now clean the lists 2309 while (!TouchedStack->IsEmpty()){ 2310 Walker = TouchedStack->PopFirst(); 2311 PredecessorList[Walker->nr] = NULL; 2312 ShortestPathList[Walker->nr] = -1; 2313 ColorList[Walker->nr] = white; 2314 } 2315 } 2316 if (MinRingSize != -1) { 2317 // go over all atoms 2318 Root = start; 2319 while(Root->next != end) { 2320 Root = Root->next; 2321 2322 if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is 2323 Walker = Root; 2324 ShortestPathList[Walker->nr] = 0; 2325 BFSStack->ClearStack(); // start with empty BFS stack 2326 BFSStack->Push(Walker); 2327 TouchedStack->Push(Walker); 2328 //*out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl; 2329 OtherAtom = Walker; 2330 while (OtherAtom != NULL) { // look for Root 2331 Walker = BFSStack->PopFirst(); 2332 //*out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl; 2333 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 2334 Binder = ListOfBondsPerAtom[Walker->nr][i]; 2335 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 2336 OtherAtom = Binder->GetOtherAtom(Walker); 2337 //*out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 2338 if (ColorList[OtherAtom->nr] == white) { 2339 TouchedStack->Push(OtherAtom); 2340 ColorList[OtherAtom->nr] = lightgray; 2341 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 2342 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 2343 //*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; 2344 if (OtherAtom->GetTrueFather()->IsCyclic) { // if the other atom is connected to a ring 2345 MinimumRingSize[Root->GetTrueFather()->nr] = ShortestPathList[OtherAtom->nr]+MinimumRingSize[OtherAtom->GetTrueFather()->nr]; 2346 OtherAtom = NULL; //break; 2347 break; 2348 } else 2349 BFSStack->Push(OtherAtom); 2350 } else { 2351 //*out << Verbose(3) << "Not Adding, has already been visited." << endl; 2352 } 2353 } else { 2354 //*out << Verbose(3) << "Not Visiting, is a back edge." << endl; 2355 } 2356 } 2357 ColorList[Walker->nr] = black; 2358 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2359 } 2360 2361 // now clean the lists 2362 while (!TouchedStack->IsEmpty()){ 2363 Walker = TouchedStack->PopFirst(); 2364 PredecessorList[Walker->nr] = NULL; 2365 ShortestPathList[Walker->nr] = -1; 2366 ColorList[Walker->nr] = white; 2367 } 2368 } 2369 *out << Verbose(1) << "Minimum ring size of " << *Root << " is " << MinimumRingSize[Root->GetTrueFather()->nr] << "." << endl; 2370 } 2371 *out << Verbose(1) << "Minimum ring size is " << MinRingSize << ", over " << NumCycles << " cycles total." << endl; 2372 } else 2373 *out << Verbose(1) << "No rings were detected in the molecular structure." << endl; 2374 2375 Free((void **)&PredecessorList, "molecule::CyclicStructureAnalysis: **PredecessorList"); 2376 Free((void **)&ShortestPathList, "molecule::CyclicStructureAnalysis: **ShortestPathList"); 2377 Free((void **)&ColorList, "molecule::CyclicStructureAnalysis: **ColorList"); 2378 delete(BFSStack); 2379 2379 }; 2380 2380 … … 2386 2386 void molecule::SetNextComponentNumber(atom *vertex, int nr) 2387 2387 { 2388 int i=0;2389 if (vertex != NULL) {2390 for(;i<NumberOfBondsPerAtom[vertex->nr];i++) {2391 if (vertex->ComponentNr[i] == -1) {// check if not yet used2392 vertex->ComponentNr[i] = nr;2393 break;2394 }2395 else if (vertex->ComponentNr[i] == nr) // if number is already present, don't add another time2396 break;// breaking here will not cause error!2397 }2398 if (i == NumberOfBondsPerAtom[vertex->nr])2399 cerr << "Error: All Component entries are already occupied!" << endl;2400 } else2401 cerr << "Error: Given vertex is NULL!" << endl;2388 int i=0; 2389 if (vertex != NULL) { 2390 for(;i<NumberOfBondsPerAtom[vertex->nr];i++) { 2391 if (vertex->ComponentNr[i] == -1) { // check if not yet used 2392 vertex->ComponentNr[i] = nr; 2393 break; 2394 } 2395 else if (vertex->ComponentNr[i] == nr) // if number is already present, don't add another time 2396 break; // breaking here will not cause error! 2397 } 2398 if (i == NumberOfBondsPerAtom[vertex->nr]) 2399 cerr << "Error: All Component entries are already occupied!" << endl; 2400 } else 2401 cerr << "Error: Given vertex is NULL!" << endl; 2402 2402 }; 2403 2403 … … 2407 2407 void molecule::OutputComponentNumber(ofstream *out, atom *vertex) 2408 2408 { 2409 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)2410 *out << vertex->ComponentNr[i] << "";2409 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2410 *out << vertex->ComponentNr[i] << " "; 2411 2411 }; 2412 2412 … … 2415 2415 void molecule::InitComponentNumbers() 2416 2416 { 2417 atom *Walker = start;2418 while(Walker->next != end) {2419 Walker = Walker->next;2420 if (Walker->ComponentNr != NULL)2421 Free((void **)&Walker->ComponentNr, "molecule::InitComponentNumbers: **Walker->ComponentNr");2422 Walker->ComponentNr = (int *) Malloc(sizeof(int)*NumberOfBondsPerAtom[Walker->nr], "molecule::InitComponentNumbers: *Walker->ComponentNr");2423 for (int i=NumberOfBondsPerAtom[Walker->nr];i--;)2424 Walker->ComponentNr[i] = -1;2425 }2417 atom *Walker = start; 2418 while(Walker->next != end) { 2419 Walker = Walker->next; 2420 if (Walker->ComponentNr != NULL) 2421 Free((void **)&Walker->ComponentNr, "molecule::InitComponentNumbers: **Walker->ComponentNr"); 2422 Walker->ComponentNr = (int *) Malloc(sizeof(int)*NumberOfBondsPerAtom[Walker->nr], "molecule::InitComponentNumbers: *Walker->ComponentNr"); 2423 for (int i=NumberOfBondsPerAtom[Walker->nr];i--;) 2424 Walker->ComponentNr[i] = -1; 2425 } 2426 2426 }; 2427 2427 … … 2432 2432 bond * molecule::FindNextUnused(atom *vertex) 2433 2433 { 2434 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)2435 if (ListOfBondsPerAtom[vertex->nr][i]->IsUsed() == white)2436 return(ListOfBondsPerAtom[vertex->nr][i]);2437 return NULL;2434 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2435 if (ListOfBondsPerAtom[vertex->nr][i]->IsUsed() == white) 2436 return(ListOfBondsPerAtom[vertex->nr][i]); 2437 return NULL; 2438 2438 }; 2439 2439 … … 2443 2443 void molecule::ResetAllBondsToUnused() 2444 2444 { 2445 bond *Binder = first;2446 while (Binder->next != last) {2447 Binder = Binder->next;2448 Binder->ResetUsed();2449 }2445 bond *Binder = first; 2446 while (Binder->next != last) { 2447 Binder = Binder->next; 2448 Binder->ResetUsed(); 2449 } 2450 2450 }; 2451 2451 … … 2454 2454 void molecule::ResetAllAtomNumbers() 2455 2455 { 2456 atom *Walker = start;2457 while (Walker->next != end) {2458 Walker = Walker->next;2459 Walker->GraphNr= -1;2460 }2456 atom *Walker = start; 2457 while (Walker->next != end) { 2458 Walker = Walker->next; 2459 Walker->GraphNr = -1; 2460 } 2461 2461 }; 2462 2462 … … 2467 2467 void OutputAlreadyVisited(ofstream *out, int *list) 2468 2468 { 2469 *out << Verbose(4) << "Already Visited Bonds:\t";2470 for(int i=1;i<=list[0];i++) *out << Verbose(0) << list[i] << "";2471 *out << endl;2469 *out << Verbose(4) << "Already Visited Bonds:\t"; 2470 for(int i=1;i<=list[0];i++) *out << Verbose(0) << list[i] << " "; 2471 *out << endl; 2472 2472 }; 2473 2473 … … 2475 2475 * The upper limit is 2476 2476 * \f[ 2477 * n = N \cdot C^k2477 * n = N \cdot C^k 2478 2478 * \f] 2479 2479 * where \f$C=2^c\f$ and c is the maximum bond degree over N number of atoms. … … 2484 2484 int molecule::GuesstimateFragmentCount(ofstream *out, int order) 2485 2485 { 2486 int c = 0;2487 int FragmentCount;2488 // get maximum bond degree2489 atom *Walker = start;2490 while (Walker->next != end) {2491 Walker = Walker->next;2492 c = (NumberOfBondsPerAtom[Walker->nr] > c) ? NumberOfBondsPerAtom[Walker->nr] : c;2493 }2494 FragmentCount = NoNonHydrogen*(1 << (c*order));2495 *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl;2496 return FragmentCount;2486 int c = 0; 2487 int FragmentCount; 2488 // get maximum bond degree 2489 atom *Walker = start; 2490 while (Walker->next != end) { 2491 Walker = Walker->next; 2492 c = (NumberOfBondsPerAtom[Walker->nr] > c) ? NumberOfBondsPerAtom[Walker->nr] : c; 2493 } 2494 FragmentCount = NoNonHydrogen*(1 << (c*order)); 2495 *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl; 2496 return FragmentCount; 2497 2497 }; 2498 2498 … … 2505 2505 bool molecule::ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet) 2506 2506 { 2507 stringstream line;2508 int AtomNr;2509 int status = 0;2510 2511 line.str(buffer);2512 while (!line.eof()) {2513 line >> AtomNr;2514 if ((AtomNr >= 0) && (AtomNr < AtomCount)) {2515 CurrentSet.insert(AtomNr);// insert at end, hence in same order as in file!2516 status++;2517 } // else it's "-1" or else and thus must not be added2518 }2519 *out << Verbose(1) << "The scanned KeySet is ";2520 for(KeySet::iterator runner = CurrentSet.begin(); runner != CurrentSet.end(); runner++) {2521 *out << (*runner) << "\t";2522 }2523 *out << endl;2524 return (status != 0);2507 stringstream line; 2508 int AtomNr; 2509 int status = 0; 2510 2511 line.str(buffer); 2512 while (!line.eof()) { 2513 line >> AtomNr; 2514 if ((AtomNr >= 0) && (AtomNr < AtomCount)) { 2515 CurrentSet.insert(AtomNr); // insert at end, hence in same order as in file! 2516 status++; 2517 } // else it's "-1" or else and thus must not be added 2518 } 2519 *out << Verbose(1) << "The scanned KeySet is "; 2520 for(KeySet::iterator runner = CurrentSet.begin(); runner != CurrentSet.end(); runner++) { 2521 *out << (*runner) << "\t"; 2522 } 2523 *out << endl; 2524 return (status != 0); 2525 2525 }; 2526 2526 … … 2537 2537 bool molecule::ParseKeySetFile(ofstream *out, char *path, Graph *&FragmentList) 2538 2538 { 2539 bool status = true;2540 ifstream InputFile;2541 stringstream line;2542 GraphTestPair testGraphInsert;2543 int NumberOfFragments = 0;2544 double TEFactor;2545 char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename");2546 2547 if (FragmentList == NULL) { // check list pointer2548 FragmentList = new Graph;2549 }2550 2551 // 1st pass: open file and read2552 *out << Verbose(1) << "Parsing the KeySet file ... " << endl;2553 sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, KEYSETFILE);2554 InputFile.open(filename);2555 if (InputFile != NULL) {2556 // each line represents a new fragment2557 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - *buffer");2558 // 1. parse keysets and insert into temp. graph2559 while (!InputFile.eof()) {2560 InputFile.getline(buffer, MAXSTRINGSIZE);2561 KeySet CurrentSet;2562 if ((strlen(buffer) > 0) && (ScanBufferIntoKeySet(out, buffer, CurrentSet))) {// if at least one valid atom was added, write config2563 testGraphInsert = FragmentList->insert(GraphPair (CurrentSet,pair<int,double>(NumberOfFragments++,1)));// store fragment number and current factor2564 if (!testGraphInsert.second) {2565 cerr << "KeySet file must be corrupt as there are two equal key sets therein!" << endl;2566 }2567 }2568 }2569 // 2. Free and done2570 InputFile.close();2571 InputFile.clear();2572 Free((void **)&buffer, "molecule::ParseKeySetFile - *buffer");2573 *out << Verbose(1) << "done." << endl;2574 } else {2575 *out << Verbose(1) << "File " << filename << " not found." << endl;2576 status = false;2577 }2578 2579 // 2nd pass: open TEFactors file and read2580 *out << Verbose(1) << "Parsing the TEFactors file ... " << endl;2581 sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, TEFACTORSFILE);2582 InputFile.open(filename);2583 if (InputFile != NULL) {2584 // 3. add found TEFactors to each keyset2585 NumberOfFragments = 0;2586 for(Graph::iterator runner = FragmentList->begin();runner != FragmentList->end(); runner++) {2587 if (!InputFile.eof()) {2588 InputFile >> TEFactor;2589 (*runner).second.second = TEFactor;2590 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl;2591 } else {2592 status = false;2593 break;2594 }2595 }2596 // 4. Free and done2597 InputFile.close();2598 *out << Verbose(1) << "done." << endl;2599 } else {2600 *out << Verbose(1) << "File " << filename << " not found." << endl;2601 status = false;2602 }2603 2604 // free memory2605 Free((void **)&filename, "molecule::ParseKeySetFile - filename");2606 2607 return status;2539 bool status = true; 2540 ifstream InputFile; 2541 stringstream line; 2542 GraphTestPair testGraphInsert; 2543 int NumberOfFragments = 0; 2544 double TEFactor; 2545 char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename"); 2546 2547 if (FragmentList == NULL) { // check list pointer 2548 FragmentList = new Graph; 2549 } 2550 2551 // 1st pass: open file and read 2552 *out << Verbose(1) << "Parsing the KeySet file ... " << endl; 2553 sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, KEYSETFILE); 2554 InputFile.open(filename); 2555 if (InputFile != NULL) { 2556 // each line represents a new fragment 2557 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - *buffer"); 2558 // 1. parse keysets and insert into temp. graph 2559 while (!InputFile.eof()) { 2560 InputFile.getline(buffer, MAXSTRINGSIZE); 2561 KeySet CurrentSet; 2562 if ((strlen(buffer) > 0) && (ScanBufferIntoKeySet(out, buffer, CurrentSet))) { // if at least one valid atom was added, write config 2563 testGraphInsert = FragmentList->insert(GraphPair (CurrentSet,pair<int,double>(NumberOfFragments++,1))); // store fragment number and current factor 2564 if (!testGraphInsert.second) { 2565 cerr << "KeySet file must be corrupt as there are two equal key sets therein!" << endl; 2566 } 2567 } 2568 } 2569 // 2. Free and done 2570 InputFile.close(); 2571 InputFile.clear(); 2572 Free((void **)&buffer, "molecule::ParseKeySetFile - *buffer"); 2573 *out << Verbose(1) << "done." << endl; 2574 } else { 2575 *out << Verbose(1) << "File " << filename << " not found." << endl; 2576 status = false; 2577 } 2578 2579 // 2nd pass: open TEFactors file and read 2580 *out << Verbose(1) << "Parsing the TEFactors file ... " << endl; 2581 sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, TEFACTORSFILE); 2582 InputFile.open(filename); 2583 if (InputFile != NULL) { 2584 // 3. add found TEFactors to each keyset 2585 NumberOfFragments = 0; 2586 for(Graph::iterator runner = FragmentList->begin();runner != FragmentList->end(); runner++) { 2587 if (!InputFile.eof()) { 2588 InputFile >> TEFactor; 2589 (*runner).second.second = TEFactor; 2590 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl; 2591 } else { 2592 status = false; 2593 break; 2594 } 2595 } 2596 // 4. Free and done 2597 InputFile.close(); 2598 *out << Verbose(1) << "done." << endl; 2599 } else { 2600 *out << Verbose(1) << "File " << filename << " not found." << endl; 2601 status = false; 2602 } 2603 2604 // free memory 2605 Free((void **)&filename, "molecule::ParseKeySetFile - filename"); 2606 2607 return status; 2608 2608 }; 2609 2609 … … 2616 2616 bool molecule::StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path) 2617 2617 { 2618 ofstream output;2619 bool status =true;2620 string line;2621 2622 // open KeySet file2623 line = path;2624 line.append("/");2625 line += FRAGMENTPREFIX;2626 line += KEYSETFILE;2627 output.open(line.c_str(), ios::out);2628 *out << Verbose(1) << "Saving key sets of the total graph ... ";2629 if(output != NULL) {2630 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) {2631 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) {2632 if (sprinter != (*runner).first.begin())2633 output << "\t";2634 output << *sprinter;2635 }2636 output << endl;2637 }2638 *out << "done." << endl;2639 } else {2640 cerr << "Unable to open " << line << " for writing keysets!" << endl;2641 status = false;2642 }2643 output.close();2644 output.clear();2645 2646 // open TEFactors file2647 line = path;2648 line.append("/");2649 line += FRAGMENTPREFIX;2650 line += TEFACTORSFILE;2651 output.open(line.c_str(), ios::out);2652 *out << Verbose(1) << "Saving TEFactors of the total graph ... ";2653 if(output != NULL) {2654 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++)2655 output << (*runner).second.second << endl;2656 *out << Verbose(1) << "done." << endl;2657 } else {2658 *out << Verbose(1) << "failed to open " << line << "." << endl;2659 status = false;2660 }2661 output.close();2662 2663 return status;2618 ofstream output; 2619 bool status = true; 2620 string line; 2621 2622 // open KeySet file 2623 line = path; 2624 line.append("/"); 2625 line += FRAGMENTPREFIX; 2626 line += KEYSETFILE; 2627 output.open(line.c_str(), ios::out); 2628 *out << Verbose(1) << "Saving key sets of the total graph ... "; 2629 if(output != NULL) { 2630 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) { 2631 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 2632 if (sprinter != (*runner).first.begin()) 2633 output << "\t"; 2634 output << *sprinter; 2635 } 2636 output << endl; 2637 } 2638 *out << "done." << endl; 2639 } else { 2640 cerr << "Unable to open " << line << " for writing keysets!" << endl; 2641 status = false; 2642 } 2643 output.close(); 2644 output.clear(); 2645 2646 // open TEFactors file 2647 line = path; 2648 line.append("/"); 2649 line += FRAGMENTPREFIX; 2650 line += TEFACTORSFILE; 2651 output.open(line.c_str(), ios::out); 2652 *out << Verbose(1) << "Saving TEFactors of the total graph ... "; 2653 if(output != NULL) { 2654 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) 2655 output << (*runner).second.second << endl; 2656 *out << Verbose(1) << "done." << endl; 2657 } else { 2658 *out << Verbose(1) << "failed to open " << line << "." << endl; 2659 status = false; 2660 } 2661 output.close(); 2662 2663 return status; 2664 2664 }; 2665 2665 … … 2672 2672 bool molecule::StoreAdjacencyToFile(ofstream *out, char *path) 2673 2673 { 2674 ofstream AdjacencyFile;2675 atom *Walker = NULL;2676 stringstream line;2677 bool status = true;2678 2679 line << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;2680 AdjacencyFile.open(line.str().c_str(), ios::out);2681 *out << Verbose(1) << "Saving adjacency list ... ";2682 if (AdjacencyFile != NULL) {2683 Walker = start;2684 while(Walker->next != end) {2685 Walker = Walker->next;2686 AdjacencyFile << Walker->nr << "\t";2687 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++)2688 AdjacencyFile << ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker)->nr << "\t";2689 AdjacencyFile << endl;2690 }2691 AdjacencyFile.close();2692 *out << Verbose(1) << "done." << endl;2693 } else {2694 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;2695 status = false;2696 }2697 2698 return status;2674 ofstream AdjacencyFile; 2675 atom *Walker = NULL; 2676 stringstream line; 2677 bool status = true; 2678 2679 line << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE; 2680 AdjacencyFile.open(line.str().c_str(), ios::out); 2681 *out << Verbose(1) << "Saving adjacency list ... "; 2682 if (AdjacencyFile != NULL) { 2683 Walker = start; 2684 while(Walker->next != end) { 2685 Walker = Walker->next; 2686 AdjacencyFile << Walker->nr << "\t"; 2687 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) 2688 AdjacencyFile << ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker)->nr << "\t"; 2689 AdjacencyFile << endl; 2690 } 2691 AdjacencyFile.close(); 2692 *out << Verbose(1) << "done." << endl; 2693 } else { 2694 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl; 2695 status = false; 2696 } 2697 2698 return status; 2699 2699 }; 2700 2700 … … 2707 2707 bool molecule::CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms) 2708 2708 { 2709 ifstream File;2710 stringstream filename;2711 bool status = true;2712 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");2713 2714 filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;2715 File.open(filename.str().c_str(), ios::out);2716 *out << Verbose(1) << "Looking at bond structure stored in adjacency file and comparing to present one ... ";2717 if (File != NULL) {2718 // allocate storage structure2719 int NonMatchNumber = 0;// will number of atoms with differing bond structure2720 int *CurrentBonds = (int *) Malloc(sizeof(int)*8, "molecule::CheckAdjacencyFileAgainstMolecule - CurrentBonds"); // contains parsed bonds of current atom2721 int CurrentBondsOfAtom;2722 2723 // Parse the file line by line and count the bonds2724 while (!File.eof()) {2725 File.getline(buffer, MAXSTRINGSIZE);2726 stringstream line;2727 line.str(buffer);2728 int AtomNr = -1;2729 line >> AtomNr;2730 CurrentBondsOfAtom = -1; // we count one too far due to line end2731 // parse into structure2732 if ((AtomNr >= 0) && (AtomNr < AtomCount)) {2733 while (!line.eof())2734 line >> CurrentBonds[ ++CurrentBondsOfAtom ];2735 // compare against present bonds2736 //cout << Verbose(2) << "Walker is " << *Walker << ", bond partners: ";2737 if (CurrentBondsOfAtom == NumberOfBondsPerAtom[AtomNr]) {2738 for(int i=0;i<NumberOfBondsPerAtom[AtomNr];i++) {2739 int id = ListOfBondsPerAtom[AtomNr][i]->GetOtherAtom(ListOfAtoms[AtomNr])->nr;2740 int j = 0;2741 for (;(j<CurrentBondsOfAtom) && (CurrentBonds[j++] != id);); // check against all parsed bonds2742 if (CurrentBonds[j-1] != id) { // no match ? Then mark in ListOfAtoms2743 ListOfAtoms[AtomNr] = NULL;2744 NonMatchNumber++;2745 status = false;2746 //out << "[" << id << "]\t";2747 } else {2748 //out << id << "\t";2749 }2750 }2751 //out << endl;2752 } else {2753 *out << "Number of bonds for Atom " << *ListOfAtoms[AtomNr] << " does not match, parsed " << CurrentBondsOfAtom << " against " << NumberOfBondsPerAtom[AtomNr] << "." << endl;2754 status = false;2755 }2756 }2757 }2758 File.close();2759 File.clear();2760 if (status) { // if equal we parse the KeySetFile2761 *out << Verbose(1) << "done: Equal." << endl;2762 status = true;2763 } else2764 *out << Verbose(1) << "done: Not equal by " << NonMatchNumber << " atoms." << endl;2765 Free((void **)&CurrentBonds, "molecule::CheckAdjacencyFileAgainstMolecule - **CurrentBonds");2766 } else {2767 *out << Verbose(1) << "Adjacency file not found." << endl;2768 status = false;2769 }2770 *out << endl;2771 Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");2772 2773 return status;2709 ifstream File; 2710 stringstream filename; 2711 bool status = true; 2712 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 2713 2714 filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE; 2715 File.open(filename.str().c_str(), ios::out); 2716 *out << Verbose(1) << "Looking at bond structure stored in adjacency file and comparing to present one ... "; 2717 if (File != NULL) { 2718 // allocate storage structure 2719 int NonMatchNumber = 0; // will number of atoms with differing bond structure 2720 int *CurrentBonds = (int *) Malloc(sizeof(int)*8, "molecule::CheckAdjacencyFileAgainstMolecule - CurrentBonds"); // contains parsed bonds of current atom 2721 int CurrentBondsOfAtom; 2722 2723 // Parse the file line by line and count the bonds 2724 while (!File.eof()) { 2725 File.getline(buffer, MAXSTRINGSIZE); 2726 stringstream line; 2727 line.str(buffer); 2728 int AtomNr = -1; 2729 line >> AtomNr; 2730 CurrentBondsOfAtom = -1; // we count one too far due to line end 2731 // parse into structure 2732 if ((AtomNr >= 0) && (AtomNr < AtomCount)) { 2733 while (!line.eof()) 2734 line >> CurrentBonds[ ++CurrentBondsOfAtom ]; 2735 // compare against present bonds 2736 //cout << Verbose(2) << "Walker is " << *Walker << ", bond partners: "; 2737 if (CurrentBondsOfAtom == NumberOfBondsPerAtom[AtomNr]) { 2738 for(int i=0;i<NumberOfBondsPerAtom[AtomNr];i++) { 2739 int id = ListOfBondsPerAtom[AtomNr][i]->GetOtherAtom(ListOfAtoms[AtomNr])->nr; 2740 int j = 0; 2741 for (;(j<CurrentBondsOfAtom) && (CurrentBonds[j++] != id);); // check against all parsed bonds 2742 if (CurrentBonds[j-1] != id) { // no match ? Then mark in ListOfAtoms 2743 ListOfAtoms[AtomNr] = NULL; 2744 NonMatchNumber++; 2745 status = false; 2746 //out << "[" << id << "]\t"; 2747 } else { 2748 //out << id << "\t"; 2749 } 2750 } 2751 //out << endl; 2752 } else { 2753 *out << "Number of bonds for Atom " << *ListOfAtoms[AtomNr] << " does not match, parsed " << CurrentBondsOfAtom << " against " << NumberOfBondsPerAtom[AtomNr] << "." << endl; 2754 status = false; 2755 } 2756 } 2757 } 2758 File.close(); 2759 File.clear(); 2760 if (status) { // if equal we parse the KeySetFile 2761 *out << Verbose(1) << "done: Equal." << endl; 2762 status = true; 2763 } else 2764 *out << Verbose(1) << "done: Not equal by " << NonMatchNumber << " atoms." << endl; 2765 Free((void **)&CurrentBonds, "molecule::CheckAdjacencyFileAgainstMolecule - **CurrentBonds"); 2766 } else { 2767 *out << Verbose(1) << "Adjacency file not found." << endl; 2768 status = false; 2769 } 2770 *out << endl; 2771 Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 2772 2773 return status; 2774 2774 }; 2775 2775 … … 2785 2785 bool molecule::CheckOrderAtSite(ofstream *out, bool *AtomMask, Graph *GlobalKeySetList, int Order, int *MinimumRingSize, char *path) 2786 2786 { 2787 atom *Walker = start;2788 bool status = false;2789 ifstream InputFile;2790 2791 // initialize mask list2792 for(int i=AtomCount;i--;)2793 AtomMask[i] = false;2794 2795 if (Order < 0) { // adaptive increase of BondOrder per site2796 if (AtomMask[AtomCount] == true)// break after one step2797 return false;2798 // parse the EnergyPerFragment file2799 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckOrderAtSite: *buffer");2800 sprintf(buffer, "%s/%s%s.dat", path, FRAGMENTPREFIX, ENERGYPERFRAGMENT);2801 InputFile.open(buffer, ios::in);2802 if ((InputFile != NULL) && (GlobalKeySetList != NULL)) {2803 // transmorph graph keyset list into indexed KeySetList2804 map<int,KeySet> IndexKeySetList;2805 for(Graph::iterator runner = GlobalKeySetList->begin(); runner != GlobalKeySetList->end(); runner++) {2806 IndexKeySetList.insert( pair<int,KeySet>(runner->second.first,runner->first) );2807 }2808 int lines = 0;2809 // count the number of lines, i.e. the number of fragments2810 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines2811 InputFile.getline(buffer, MAXSTRINGSIZE);2812 while(!InputFile.eof()) {2813 InputFile.getline(buffer, MAXSTRINGSIZE);2814 lines++;2815 }2816 //*out << Verbose(2) << "Scanned " << lines-1 << " lines." << endl;// one endline too much2817 InputFile.clear();2818 InputFile.seekg(ios::beg);2819 map<int, pair<double,int> > AdaptiveCriteriaList;// (Root No., (Value, Order)) !2820 int No, FragOrder;2821 double Value;2822 // each line represents a fragment root (Atom::nr) id and its energy contribution2823 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines2824 InputFile.getline(buffer, MAXSTRINGSIZE);2825 while(!InputFile.eof()) {2826 InputFile.getline(buffer, MAXSTRINGSIZE);2827 if (strlen(buffer) > 2) {2828 //*out << Verbose(2) << "Scanning: " << buffer << endl;2829 stringstream line(buffer);2830 line >> FragOrder;2831 line >> ws >> No;2832 line >> ws >> Value; // skip time entry2833 line >> ws >> Value;2834 No -= 1;// indices start at 1 in file, not 02835 //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl;2836 2837 // clean the list of those entries that have been superceded by higher order terms already2838 map<int,KeySet>::iterator marker = IndexKeySetList.find(No);// find keyset to Frag No.2839 if (marker != IndexKeySetList.end()) {// if found2840 Value *= 1 + MYEPSILON*(*((*marker).second.begin()));// in case of equal energies this makes em not equal without changing anything actually2841 // 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 AtomMask2842 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) ));2843 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first;2844 if (!InsertedElement.second) { // this root is already present2845 if ((*PresentItem).second.second < FragOrder)// if order there is lower, update entry with higher-order term2846 //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)2847 {// if value is smaller, update value and order2848 (*PresentItem).second.first = fabs(Value);2849 (*PresentItem).second.second = FragOrder;2850 *out << Verbose(2) << "Updated element (" <<(*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;2851 } else {2852 *out << Verbose(2) << "Did not update element " <<(*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl;2853 }2854 } else {2855 *out << Verbose(2) << "Inserted element (" <<(*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;2856 }2857 } else {2858 *out << Verbose(1) << "No Fragment under No. " << No << "found." << endl;2859 }2860 }2861 }2862 // then map back onto (Value, (Root Nr., Order)) (i.e. sorted by value to pick the highest ones)2863 map<double, pair<int,int> > FinalRootCandidates;2864 *out << Verbose(1) << "Root candidate list is: " << endl;2865 for(map<int, pair<double,int> >::iterator runner = AdaptiveCriteriaList.begin(); runner != AdaptiveCriteriaList.end(); runner++) {2866 Walker = FindAtom((*runner).first);2867 if (Walker != NULL) {2868 //if ((*runner).second.second >= Walker->AdaptiveOrder) { // only insert if this is an "active" root site for the current order2869 if (!Walker->MaxOrder) {2870 *out << Verbose(2) << "(" << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "])" << endl;2871 FinalRootCandidates.insert( make_pair( (*runner).second.first, pair<int,int>((*runner).first, (*runner).second.second) ) );2872 } else {2873 *out << Verbose(2) << "Excluding (" << *Walker << ", " << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "]), as it has reached its maximum order." << endl;2874 }2875 } else {2876 cerr << "Atom No. " << (*runner).second.first << " was not found in this molecule." << endl;2877 }2878 }2879 // pick the ones still below threshold and mark as to be adaptively updated2880 for(map<double, pair<int,int> >::iterator runner = FinalRootCandidates.upper_bound(pow(10.,Order)); runner != FinalRootCandidates.end(); runner++) {2881 No = (*runner).second.first;2882 Walker = FindAtom(No);2883 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) {2884 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl;2885 AtomMask[No] = true;2886 status = true;2887 //} else2888 //*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;2889 }2890 // close and done2891 InputFile.close();2892 InputFile.clear();2893 } else {2894 cerr << "Unable to parse " << buffer << " file, incrementing all." << endl;2895 while (Walker->next != end) {2896 Walker = Walker->next;2897 #ifdef ADDHYDROGEN2898 if (Walker->type->Z != 1) // skip hydrogen2899 #endif2900 {2901 AtomMask[Walker->nr] = true;// include all (non-hydrogen) atoms2902 status = true;2903 }2904 }2905 }2906 Free((void **)&buffer, "molecule::CheckOrderAtSite: *buffer");2907 // pick a given number of highest values and set AtomMask2908 } else { // global increase of Bond Order2909 while (Walker->next != end) {2910 Walker = Walker->next;2911 #ifdef ADDHYDROGEN2912 if (Walker->type->Z != 1) // skip hydrogen2913 #endif2914 {2915 AtomMask[Walker->nr] = true;// include all (non-hydrogen) atoms2916 if ((Order != 0) && (Walker->AdaptiveOrder < Order)) // && (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]))2917 status = true;2918 }2919 }2920 if ((Order == 0) && (AtomMask[AtomCount] == false))// single stepping, just check2921 status = true;2922 2923 if (!status) {2924 if (Order == 0)2925 *out << Verbose(1) << "Single stepping done." << endl;2926 else2927 *out << Verbose(1) << "Order at every site is already equal or above desired order " << Order << "." << endl;2928 }2929 }2930 2931 // print atom mask for debugging2932 *out << "";2933 for(int i=0;i<AtomCount;i++)2934 *out << (i % 10);2935 *out << endl << "Atom mask is: ";2936 for(int i=0;i<AtomCount;i++)2937 *out << (AtomMask[i] ? "t" : "f");2938 *out << endl;2939 2940 return status;2787 atom *Walker = start; 2788 bool status = false; 2789 ifstream InputFile; 2790 2791 // initialize mask list 2792 for(int i=AtomCount;i--;) 2793 AtomMask[i] = false; 2794 2795 if (Order < 0) { // adaptive increase of BondOrder per site 2796 if (AtomMask[AtomCount] == true) // break after one step 2797 return false; 2798 // parse the EnergyPerFragment file 2799 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckOrderAtSite: *buffer"); 2800 sprintf(buffer, "%s/%s%s.dat", path, FRAGMENTPREFIX, ENERGYPERFRAGMENT); 2801 InputFile.open(buffer, ios::in); 2802 if ((InputFile != NULL) && (GlobalKeySetList != NULL)) { 2803 // transmorph graph keyset list into indexed KeySetList 2804 map<int,KeySet> IndexKeySetList; 2805 for(Graph::iterator runner = GlobalKeySetList->begin(); runner != GlobalKeySetList->end(); runner++) { 2806 IndexKeySetList.insert( pair<int,KeySet>(runner->second.first,runner->first) ); 2807 } 2808 int lines = 0; 2809 // count the number of lines, i.e. the number of fragments 2810 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines 2811 InputFile.getline(buffer, MAXSTRINGSIZE); 2812 while(!InputFile.eof()) { 2813 InputFile.getline(buffer, MAXSTRINGSIZE); 2814 lines++; 2815 } 2816 //*out << Verbose(2) << "Scanned " << lines-1 << " lines." << endl; // one endline too much 2817 InputFile.clear(); 2818 InputFile.seekg(ios::beg); 2819 map<int, pair<double,int> > AdaptiveCriteriaList; // (Root No., (Value, Order)) ! 2820 int No, FragOrder; 2821 double Value; 2822 // each line represents a fragment root (Atom::nr) id and its energy contribution 2823 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines 2824 InputFile.getline(buffer, MAXSTRINGSIZE); 2825 while(!InputFile.eof()) { 2826 InputFile.getline(buffer, MAXSTRINGSIZE); 2827 if (strlen(buffer) > 2) { 2828 //*out << Verbose(2) << "Scanning: " << buffer << endl; 2829 stringstream line(buffer); 2830 line >> FragOrder; 2831 line >> ws >> No; 2832 line >> ws >> Value; // skip time entry 2833 line >> ws >> Value; 2834 No -= 1; // indices start at 1 in file, not 0 2835 //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl; 2836 2837 // clean the list of those entries that have been superceded by higher order terms already 2838 map<int,KeySet>::iterator marker = IndexKeySetList.find(No); // find keyset to Frag No. 2839 if (marker != IndexKeySetList.end()) { // if found 2840 Value *= 1 + MYEPSILON*(*((*marker).second.begin())); // in case of equal energies this makes em not equal without changing anything actually 2841 // 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 2842 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) )); 2843 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 2844 if (!InsertedElement.second) { // this root is already present 2845 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term 2846 //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) 2847 { // if value is smaller, update value and order 2848 (*PresentItem).second.first = fabs(Value); 2849 (*PresentItem).second.second = FragOrder; 2850 *out << Verbose(2) << "Updated element (" << (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl; 2851 } else { 2852 *out << Verbose(2) << "Did not update element " << (*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl; 2853 } 2854 } else { 2855 *out << Verbose(2) << "Inserted element (" << (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl; 2856 } 2857 } else { 2858 *out << Verbose(1) << "No Fragment under No. " << No << "found." << endl; 2859 } 2860 } 2861 } 2862 // then map back onto (Value, (Root Nr., Order)) (i.e. sorted by value to pick the highest ones) 2863 map<double, pair<int,int> > FinalRootCandidates; 2864 *out << Verbose(1) << "Root candidate list is: " << endl; 2865 for(map<int, pair<double,int> >::iterator runner = AdaptiveCriteriaList.begin(); runner != AdaptiveCriteriaList.end(); runner++) { 2866 Walker = FindAtom((*runner).first); 2867 if (Walker != NULL) { 2868 //if ((*runner).second.second >= Walker->AdaptiveOrder) { // only insert if this is an "active" root site for the current order 2869 if (!Walker->MaxOrder) { 2870 *out << Verbose(2) << "(" << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "])" << endl; 2871 FinalRootCandidates.insert( make_pair( (*runner).second.first, pair<int,int>((*runner).first, (*runner).second.second) ) ); 2872 } else { 2873 *out << Verbose(2) << "Excluding (" << *Walker << ", " << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "]), as it has reached its maximum order." << endl; 2874 } 2875 } else { 2876 cerr << "Atom No. " << (*runner).second.first << " was not found in this molecule." << endl; 2877 } 2878 } 2879 // pick the ones still below threshold and mark as to be adaptively updated 2880 for(map<double, pair<int,int> >::iterator runner = FinalRootCandidates.upper_bound(pow(10.,Order)); runner != FinalRootCandidates.end(); runner++) { 2881 No = (*runner).second.first; 2882 Walker = FindAtom(No); 2883 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) { 2884 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 2885 AtomMask[No] = true; 2886 status = true; 2887 //} else 2888 //*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; 2889 } 2890 // close and done 2891 InputFile.close(); 2892 InputFile.clear(); 2893 } else { 2894 cerr << "Unable to parse " << buffer << " file, incrementing all." << endl; 2895 while (Walker->next != end) { 2896 Walker = Walker->next; 2897 #ifdef ADDHYDROGEN 2898 if (Walker->type->Z != 1) // skip hydrogen 2899 #endif 2900 { 2901 AtomMask[Walker->nr] = true; // include all (non-hydrogen) atoms 2902 status = true; 2903 } 2904 } 2905 } 2906 Free((void **)&buffer, "molecule::CheckOrderAtSite: *buffer"); 2907 // pick a given number of highest values and set AtomMask 2908 } else { // global increase of Bond Order 2909 while (Walker->next != end) { 2910 Walker = Walker->next; 2911 #ifdef ADDHYDROGEN 2912 if (Walker->type->Z != 1) // skip hydrogen 2913 #endif 2914 { 2915 AtomMask[Walker->nr] = true; // include all (non-hydrogen) atoms 2916 if ((Order != 0) && (Walker->AdaptiveOrder < Order)) // && (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr])) 2917 status = true; 2918 } 2919 } 2920 if ((Order == 0) && (AtomMask[AtomCount] == false)) // single stepping, just check 2921 status = true; 2922 2923 if (!status) { 2924 if (Order == 0) 2925 *out << Verbose(1) << "Single stepping done." << endl; 2926 else 2927 *out << Verbose(1) << "Order at every site is already equal or above desired order " << Order << "." << endl; 2928 } 2929 } 2930 2931 // print atom mask for debugging 2932 *out << " "; 2933 for(int i=0;i<AtomCount;i++) 2934 *out << (i % 10); 2935 *out << endl << "Atom mask is: "; 2936 for(int i=0;i<AtomCount;i++) 2937 *out << (AtomMask[i] ? "t" : "f"); 2938 *out << endl; 2939 2940 return status; 2941 2941 }; 2942 2942 … … 2948 2948 bool molecule::CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex) 2949 2949 { 2950 element *runner = elemente->start;2951 int AtomNo = 0;2952 atom *Walker = NULL;2953 2954 if (SortIndex != NULL) {2955 *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl;2956 return false;2957 }2958 SortIndex = (int *) Malloc(sizeof(int)*AtomCount, "molecule::FragmentMolecule: *SortIndex");2959 for(int i=AtomCount;i--;)2960 SortIndex[i] = -1;2961 while (runner->next != elemente->end) { // go through every element2962 runner = runner->next;2963 if (ElementsInMolecule[runner->Z]) { // if this element got atoms2964 Walker = start;2965 while (Walker->next != end) { // go through every atom of this element2966 Walker = Walker->next;2967 if (Walker->type->Z == runner->Z) // if this atom fits to element2968 SortIndex[Walker->nr] = AtomNo++;2969 }2970 }2971 }2972 return true;2950 element *runner = elemente->start; 2951 int AtomNo = 0; 2952 atom *Walker = NULL; 2953 2954 if (SortIndex != NULL) { 2955 *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl; 2956 return false; 2957 } 2958 SortIndex = (int *) Malloc(sizeof(int)*AtomCount, "molecule::FragmentMolecule: *SortIndex"); 2959 for(int i=AtomCount;i--;) 2960 SortIndex[i] = -1; 2961 while (runner->next != elemente->end) { // go through every element 2962 runner = runner->next; 2963 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 2964 Walker = start; 2965 while (Walker->next != end) { // go through every atom of this element 2966 Walker = Walker->next; 2967 if (Walker->type->Z == runner->Z) // if this atom fits to element 2968 SortIndex[Walker->nr] = AtomNo++; 2969 } 2970 } 2971 } 2972 return true; 2973 2973 }; 2974 2974 … … 2979 2979 y contribution", and that's why this consciously not done in the following loop) 2980 2980 * -# in a loop over all subgraphs 2981 * -# calls FragmentBOSSANOVA with this RootStack and within the subgraph molecule structure2982 * -# creates molecule (fragment)s from the returned keysets (StoreFragmentFromKeySet)2981 * -# calls FragmentBOSSANOVA with this RootStack and within the subgraph molecule structure 2982 * -# creates molecule (fragment)s from the returned keysets (StoreFragmentFromKeySet) 2983 2983 * -# combines the generated molecule lists from all subgraphs 2984 2984 * -# saves to disk: fragment configs, adjacency, orderatsite, keyset files … … 2993 2993 int molecule::FragmentMolecule(ofstream *out, int Order, config *configuration) 2994 2994 { 2995 MoleculeListClass *BondFragments = NULL;2996 int *SortIndex = NULL;2997 int *MinimumRingSize = new int[AtomCount];2998 int FragmentCounter;2999 MoleculeLeafClass *MolecularWalker = NULL;3000 MoleculeLeafClass *Subgraphs = NULL;// list of subgraphs from DFS analysis3001 fstream File;3002 bool FragmentationToDo = true;3003 class StackClass<bond *> *BackEdgeStack = NULL, *LocalBackEdgeStack = NULL;3004 bool CheckOrder = false;3005 Graph **FragmentList = NULL;3006 Graph *ParsedFragmentList = NULL;3007 Graph TotalGraph;// graph with all keysets however local numbers3008 int TotalNumberOfKeySets = 0;3009 atom **ListOfAtoms = NULL;3010 atom ***ListOfLocalAtoms = NULL;3011 bool *AtomMask = NULL;3012 3013 *out << endl;2995 MoleculeListClass *BondFragments = NULL; 2996 int *SortIndex = NULL; 2997 int *MinimumRingSize = new int[AtomCount]; 2998 int FragmentCounter; 2999 MoleculeLeafClass *MolecularWalker = NULL; 3000 MoleculeLeafClass *Subgraphs = NULL; // list of subgraphs from DFS analysis 3001 fstream File; 3002 bool FragmentationToDo = true; 3003 class StackClass<bond *> *BackEdgeStack = NULL, *LocalBackEdgeStack = NULL; 3004 bool CheckOrder = false; 3005 Graph **FragmentList = NULL; 3006 Graph *ParsedFragmentList = NULL; 3007 Graph TotalGraph; // graph with all keysets however local numbers 3008 int TotalNumberOfKeySets = 0; 3009 atom **ListOfAtoms = NULL; 3010 atom ***ListOfLocalAtoms = NULL; 3011 bool *AtomMask = NULL; 3012 3013 *out << endl; 3014 3014 #ifdef ADDHYDROGEN 3015 *out << Verbose(0) << "I will treat hydrogen special and saturate dangling bonds with it." << endl;3015 *out << Verbose(0) << "I will treat hydrogen special and saturate dangling bonds with it." << endl; 3016 3016 #else 3017 *out << Verbose(0) << "Hydrogen is treated just like the rest of the lot." << endl;3017 *out << Verbose(0) << "Hydrogen is treated just like the rest of the lot." << endl; 3018 3018 #endif 3019 3019 3020 // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++3021 3022 // ===== 1. Check whether bond structure is same as stored in files ====3023 3024 // fill the adjacency list3025 CreateListOfBondsPerAtom(out);3026 3027 // create lookup table for Atom::nr3028 FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount);3029 3030 // === compare it with adjacency file ===3031 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms);3032 Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms");3033 3034 // ===== 2. perform a DFS analysis to gather info on cyclic structure and a list of disconnected subgraphs =====3035 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack);3036 // fill the bond structure of the individually stored subgraphs3037 Subgraphs->next->FillBondStructureFromReference(out, this, (FragmentCounter = 0), ListOfLocalAtoms, false);// we want to keep the created ListOfLocalAtoms3038 // analysis of the cycles (print rings, get minimum cycle length) for each subgraph3039 for(int i=AtomCount;i--;)3040 MinimumRingSize[i] = AtomCount;3041 MolecularWalker = Subgraphs;3042 FragmentCounter = 0;3043 while (MolecularWalker->next != NULL) {3044 MolecularWalker = MolecularWalker->next;3045 LocalBackEdgeStack = new StackClass<bond *> (MolecularWalker->Leaf->BondCount);3046 // // check the list of local atoms for debugging3047 // *out << Verbose(0) << "ListOfLocalAtoms for this subgraph is:" << endl;3048 // for (int i=0;i<AtomCount;i++)3049 // if (ListOfLocalAtoms[FragmentCounter][i] == NULL)3050 // *out << "\tNULL";3051 // else3052 // *out << "\t" << ListOfLocalAtoms[FragmentCounter][i]->Name;3053 *out << Verbose(0) << "Gathering local back edges for subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;3054 MolecularWalker->Leaf->PickLocalBackEdges(out, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack);3055 *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;3056 MolecularWalker->Leaf->CyclicStructureAnalysis(out, LocalBackEdgeStack, MinimumRingSize);3057 *out << Verbose(0) << "Done with Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;3058 delete(LocalBackEdgeStack);3059 }3060 3061 // ===== 3. if structure still valid, parse key set file and others =====3062 FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList);3063 3064 // ===== 4. check globally whether there's something to do actually (first adaptivity check)3065 FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath);3066 3067 // =================================== Begin of FRAGMENTATION ===============================3068 // ===== 6a. assign each keyset to its respective subgraph =====3069 Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true);3070 3071 // ===== 6b. prepare and go into the adaptive (Order<0), single-step (Order==0) or incremental (Order>0) cycle3072 KeyStack *RootStack = new KeyStack[Subgraphs->next->Count()];3073 AtomMask = new bool[AtomCount+1];3074 AtomMask[AtomCount] = false;3075 FragmentationToDo = false;// if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards3076 while ((CheckOrder = CheckOrderAtSite(out, AtomMask, ParsedFragmentList, Order, MinimumRingSize, configuration->configpath))) {3077 FragmentationToDo = FragmentationToDo || CheckOrder;3078 AtomMask[AtomCount] = true;// last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite()3079 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) =====3080 Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0));3081 3082 // ===== 7. fill the bond fragment list =====3083 FragmentCounter = 0;3084 MolecularWalker = Subgraphs;3085 while (MolecularWalker->next != NULL) {3086 MolecularWalker = MolecularWalker->next;3087 *out << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl;3088 //MolecularWalker->Leaf->OutputListOfBonds(out);// output ListOfBondsPerAtom for debugging3089 if (MolecularWalker->Leaf->first->next != MolecularWalker->Leaf->last) {3090 // call BOSSANOVA method3091 *out << Verbose(0) << endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= " << endl;3092 MolecularWalker->Leaf->FragmentBOSSANOVA(out, FragmentList[FragmentCounter], RootStack[FragmentCounter], MinimumRingSize);3093 } else {3094 cerr << "Subgraph " << MolecularWalker << " has no atoms!" << endl;3095 }3096 FragmentCounter++;// next fragment list3097 }3098 }3099 delete[](RootStack);3100 delete[](AtomMask);3101 delete(ParsedFragmentList);3102 delete[](MinimumRingSize);3103 3104 3105 // ==================================== End of FRAGMENTATION ============================================3106 3107 // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf)3108 Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph);3109 3110 // free subgraph memory again3111 FragmentCounter = 0;3112 if (Subgraphs != NULL) {3113 while (Subgraphs->next != NULL) {3114 Subgraphs = Subgraphs->next;3115 delete(FragmentList[FragmentCounter++]);3116 delete(Subgraphs->previous);3117 }3118 delete(Subgraphs);3119 }3120 Free((void **)&FragmentList, "molecule::FragmentMolecule - **FragmentList");3121 3122 // ===== 8b. gather keyset lists (graphs) from all subgraphs and transform into MoleculeListClass =====3123 //if (FragmentationToDo) {// we should always store the fragments again as coordination might have changed slightly without changing bond structure3124 // allocate memory for the pointer array and transmorph graphs into full molecular fragments3125 BondFragments = new MoleculeListClass();3126 int k=0;3127 for(Graph::iterator runner = TotalGraph.begin(); runner != TotalGraph.end(); runner++) {3128 KeySet test = (*runner).first;3129 *out << "Fragment No." << (*runner).second.first << " with TEFactor " << (*runner).second.second << "." << endl;3130 BondFragments->insert(StoreFragmentFromKeySet(out, test, configuration));3131 k++;3132 }3133 *out << k << "/" << BondFragments->ListOfMolecules.size() << " fragments generated from the keysets." << endl;3134 3135 // ===== 9. Save fragments' configuration and keyset files et al to disk ===3136 if (BondFragments->ListOfMolecules.size() != 0) {3137 // create the SortIndex from BFS labels to order in the config file3138 CreateMappingLabelsToConfigSequence(out, SortIndex);3139 3140 *out << Verbose(1) << "Writing " << BondFragments->ListOfMolecules.size() << " possible bond fragmentation configs" << endl;3141 if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex))3142 *out << Verbose(1) << "All configs written." << endl;3143 else3144 *out << Verbose(1) << "Some config writing failed." << endl;3145 3146 // store force index reference file3147 BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex);3148 3149 // store keysets file3150 StoreKeySetFile(out, TotalGraph, configuration->configpath);3151 3152 // store Adjacency file3153 StoreAdjacencyToFile(out, configuration->configpath);3154 3155 // store Hydrogen saturation correction file3156 BondFragments->AddHydrogenCorrection(out, configuration->configpath);3157 3158 // store adaptive orders into file3159 StoreOrderAtSiteFile(out, configuration->configpath);3160 3161 // restore orbital and Stop values3162 CalculateOrbitals(*configuration);3163 3164 // free memory for bond part3165 *out << Verbose(1) << "Freeing bond memory" << endl;3166 delete(FragmentList); // remove bond molecule from memory3167 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex");3168 } else3169 *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl;3170 //} else3171 //*out << Verbose(1) << "No fragments to store." << endl;3172 *out << Verbose(0) << "End of bond fragmentation." << endl;3173 3174 return ((int)(!FragmentationToDo)+1);// 1 - continue, 2 - stop (no fragmentation occured)3020 // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++ 3021 3022 // ===== 1. Check whether bond structure is same as stored in files ==== 3023 3024 // fill the adjacency list 3025 CreateListOfBondsPerAtom(out); 3026 3027 // create lookup table for Atom::nr 3028 FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount); 3029 3030 // === compare it with adjacency file === 3031 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 3032 Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms"); 3033 3034 // ===== 2. perform a DFS analysis to gather info on cyclic structure and a list of disconnected subgraphs ===== 3035 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack); 3036 // fill the bond structure of the individually stored subgraphs 3037 Subgraphs->next->FillBondStructureFromReference(out, this, (FragmentCounter = 0), ListOfLocalAtoms, false); // we want to keep the created ListOfLocalAtoms 3038 // analysis of the cycles (print rings, get minimum cycle length) for each subgraph 3039 for(int i=AtomCount;i--;) 3040 MinimumRingSize[i] = AtomCount; 3041 MolecularWalker = Subgraphs; 3042 FragmentCounter = 0; 3043 while (MolecularWalker->next != NULL) { 3044 MolecularWalker = MolecularWalker->next; 3045 LocalBackEdgeStack = new StackClass<bond *> (MolecularWalker->Leaf->BondCount); 3046 // // check the list of local atoms for debugging 3047 // *out << Verbose(0) << "ListOfLocalAtoms for this subgraph is:" << endl; 3048 // for (int i=0;i<AtomCount;i++) 3049 // if (ListOfLocalAtoms[FragmentCounter][i] == NULL) 3050 // *out << "\tNULL"; 3051 // else 3052 // *out << "\t" << ListOfLocalAtoms[FragmentCounter][i]->Name; 3053 *out << Verbose(0) << "Gathering local back edges for subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3054 MolecularWalker->Leaf->PickLocalBackEdges(out, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack); 3055 *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3056 MolecularWalker->Leaf->CyclicStructureAnalysis(out, LocalBackEdgeStack, MinimumRingSize); 3057 *out << Verbose(0) << "Done with Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3058 delete(LocalBackEdgeStack); 3059 } 3060 3061 // ===== 3. if structure still valid, parse key set file and others ===== 3062 FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList); 3063 3064 // ===== 4. check globally whether there's something to do actually (first adaptivity check) 3065 FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath); 3066 3067 // =================================== Begin of FRAGMENTATION =============================== 3068 // ===== 6a. assign each keyset to its respective subgraph ===== 3069 Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true); 3070 3071 // ===== 6b. prepare and go into the adaptive (Order<0), single-step (Order==0) or incremental (Order>0) cycle 3072 KeyStack *RootStack = new KeyStack[Subgraphs->next->Count()]; 3073 AtomMask = new bool[AtomCount+1]; 3074 AtomMask[AtomCount] = false; 3075 FragmentationToDo = false; // if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards 3076 while ((CheckOrder = CheckOrderAtSite(out, AtomMask, ParsedFragmentList, Order, MinimumRingSize, configuration->configpath))) { 3077 FragmentationToDo = FragmentationToDo || CheckOrder; 3078 AtomMask[AtomCount] = true; // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite() 3079 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 3080 Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0)); 3081 3082 // ===== 7. fill the bond fragment list ===== 3083 FragmentCounter = 0; 3084 MolecularWalker = Subgraphs; 3085 while (MolecularWalker->next != NULL) { 3086 MolecularWalker = MolecularWalker->next; 3087 *out << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl; 3088 //MolecularWalker->Leaf->OutputListOfBonds(out); // output ListOfBondsPerAtom for debugging 3089 if (MolecularWalker->Leaf->first->next != MolecularWalker->Leaf->last) { 3090 // call BOSSANOVA method 3091 *out << Verbose(0) << endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= " << endl; 3092 MolecularWalker->Leaf->FragmentBOSSANOVA(out, FragmentList[FragmentCounter], RootStack[FragmentCounter], MinimumRingSize); 3093 } else { 3094 cerr << "Subgraph " << MolecularWalker << " has no atoms!" << endl; 3095 } 3096 FragmentCounter++; // next fragment list 3097 } 3098 } 3099 delete[](RootStack); 3100 delete[](AtomMask); 3101 delete(ParsedFragmentList); 3102 delete[](MinimumRingSize); 3103 3104 3105 // ==================================== End of FRAGMENTATION ============================================ 3106 3107 // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf) 3108 Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph); 3109 3110 // free subgraph memory again 3111 FragmentCounter = 0; 3112 if (Subgraphs != NULL) { 3113 while (Subgraphs->next != NULL) { 3114 Subgraphs = Subgraphs->next; 3115 delete(FragmentList[FragmentCounter++]); 3116 delete(Subgraphs->previous); 3117 } 3118 delete(Subgraphs); 3119 } 3120 Free((void **)&FragmentList, "molecule::FragmentMolecule - **FragmentList"); 3121 3122 // ===== 8b. gather keyset lists (graphs) from all subgraphs and transform into MoleculeListClass ===== 3123 //if (FragmentationToDo) { // we should always store the fragments again as coordination might have changed slightly without changing bond structure 3124 // allocate memory for the pointer array and transmorph graphs into full molecular fragments 3125 BondFragments = new MoleculeListClass(); 3126 int k=0; 3127 for(Graph::iterator runner = TotalGraph.begin(); runner != TotalGraph.end(); runner++) { 3128 KeySet test = (*runner).first; 3129 *out << "Fragment No." << (*runner).second.first << " with TEFactor " << (*runner).second.second << "." << endl; 3130 BondFragments->insert(StoreFragmentFromKeySet(out, test, configuration)); 3131 k++; 3132 } 3133 *out << k << "/" << BondFragments->ListOfMolecules.size() << " fragments generated from the keysets." << endl; 3134 3135 // ===== 9. Save fragments' configuration and keyset files et al to disk === 3136 if (BondFragments->ListOfMolecules.size() != 0) { 3137 // create the SortIndex from BFS labels to order in the config file 3138 CreateMappingLabelsToConfigSequence(out, SortIndex); 3139 3140 *out << Verbose(1) << "Writing " << BondFragments->ListOfMolecules.size() << " possible bond fragmentation configs" << endl; 3141 if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex)) 3142 *out << Verbose(1) << "All configs written." << endl; 3143 else 3144 *out << Verbose(1) << "Some config writing failed." << endl; 3145 3146 // store force index reference file 3147 BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex); 3148 3149 // store keysets file 3150 StoreKeySetFile(out, TotalGraph, configuration->configpath); 3151 3152 // store Adjacency file 3153 StoreAdjacencyToFile(out, configuration->configpath); 3154 3155 // store Hydrogen saturation correction file 3156 BondFragments->AddHydrogenCorrection(out, configuration->configpath); 3157 3158 // store adaptive orders into file 3159 StoreOrderAtSiteFile(out, configuration->configpath); 3160 3161 // restore orbital and Stop values 3162 CalculateOrbitals(*configuration); 3163 3164 // free memory for bond part 3165 *out << Verbose(1) << "Freeing bond memory" << endl; 3166 delete(FragmentList); // remove bond molecule from memory 3167 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3168 } else 3169 *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl; 3170 //} else 3171 // *out << Verbose(1) << "No fragments to store." << endl; 3172 *out << Verbose(0) << "End of bond fragmentation." << endl; 3173 3174 return ((int)(!FragmentationToDo)+1); // 1 - continue, 2 - stop (no fragmentation occured) 3175 3175 }; 3176 3176 … … 3185 3185 bool molecule::PickLocalBackEdges(ofstream *out, atom **ListOfLocalAtoms, class StackClass<bond *> *&ReferenceStack, class StackClass<bond *> *&LocalStack) 3186 3186 { 3187 bool status = true;3188 if (ReferenceStack->IsEmpty()) {3189 cerr << "ReferenceStack is empty!" << endl;3190 return false;3191 }3192 bond *Binder = ReferenceStack->PopFirst();3193 bond *FirstBond = Binder;// mark the first bond, so that we don't loop through the stack indefinitely3194 atom *Walker = NULL, *OtherAtom = NULL;3195 ReferenceStack->Push(Binder);3196 3197 do {// go through all bonds and push local ones3198 Walker = ListOfLocalAtoms[Binder->leftatom->nr];// get one atom in the reference molecule3199 if (Walker != NULL) // if this Walker exists in the subgraph ...3200 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {// go through the local list of bonds3201 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);3202 if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond3203 LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]);3204 *out << Verbose(3) << "Found local edge " << *(ListOfBondsPerAtom[Walker->nr][i]) << "." << endl;3205 break;3206 }3207 }3208 Binder = ReferenceStack->PopFirst();// loop the stack for next item3209 *out << Verbose(3) << "Current candidate edge " << Binder << "." << endl;3210 ReferenceStack->Push(Binder);3211 } while (FirstBond != Binder);3212 3213 return status;3187 bool status = true; 3188 if (ReferenceStack->IsEmpty()) { 3189 cerr << "ReferenceStack is empty!" << endl; 3190 return false; 3191 } 3192 bond *Binder = ReferenceStack->PopFirst(); 3193 bond *FirstBond = Binder; // mark the first bond, so that we don't loop through the stack indefinitely 3194 atom *Walker = NULL, *OtherAtom = NULL; 3195 ReferenceStack->Push(Binder); 3196 3197 do { // go through all bonds and push local ones 3198 Walker = ListOfLocalAtoms[Binder->leftatom->nr]; // get one atom in the reference molecule 3199 if (Walker != NULL) // if this Walker exists in the subgraph ... 3200 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through the local list of bonds 3201 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 3202 if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond 3203 LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]); 3204 *out << Verbose(3) << "Found local edge " << *(ListOfBondsPerAtom[Walker->nr][i]) << "." << endl; 3205 break; 3206 } 3207 } 3208 Binder = ReferenceStack->PopFirst(); // loop the stack for next item 3209 *out << Verbose(3) << "Current candidate edge " << Binder << "." << endl; 3210 ReferenceStack->Push(Binder); 3211 } while (FirstBond != Binder); 3212 3213 return status; 3214 3214 }; 3215 3215 … … 3222 3222 bool molecule::StoreOrderAtSiteFile(ofstream *out, char *path) 3223 3223 { 3224 stringstream line;3225 ofstream file;3226 3227 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE;3228 file.open(line.str().c_str());3229 *out << Verbose(1) << "Writing OrderAtSite " << ORDERATSITEFILE << " ... " << endl;3230 if (file != NULL) {3231 atom *Walker = start;3232 while (Walker->next != end) {3233 Walker = Walker->next;3234 file << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << endl;3235 *out << Verbose(2) << "Storing: " << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << "." << endl;3236 }3237 file.close();3238 *out << Verbose(1) << "done." << endl;3239 return true;3240 } else {3241 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;3242 return false;3243 }3224 stringstream line; 3225 ofstream file; 3226 3227 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE; 3228 file.open(line.str().c_str()); 3229 *out << Verbose(1) << "Writing OrderAtSite " << ORDERATSITEFILE << " ... " << endl; 3230 if (file != NULL) { 3231 atom *Walker = start; 3232 while (Walker->next != end) { 3233 Walker = Walker->next; 3234 file << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << endl; 3235 *out << Verbose(2) << "Storing: " << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << "." << endl; 3236 } 3237 file.close(); 3238 *out << Verbose(1) << "done." << endl; 3239 return true; 3240 } else { 3241 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl; 3242 return false; 3243 } 3244 3244 }; 3245 3245 … … 3253 3253 bool molecule::ParseOrderAtSiteFromFile(ofstream *out, char *path) 3254 3254 { 3255 unsigned char *OrderArray = (unsigned char *) Malloc(sizeof(unsigned char)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *OrderArray");3256 bool *MaxArray = (bool *) Malloc(sizeof(bool)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *MaxArray");3257 bool status;3258 int AtomNr, value;3259 stringstream line;3260 ifstream file;3261 3262 *out << Verbose(1) << "Begin of ParseOrderAtSiteFromFile" << endl;3263 for(int i=AtomCount;i--;)3264 OrderArray[i] = 0;3265 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE;3266 file.open(line.str().c_str());3267 if (file != NULL) {3268 for (int i=AtomCount;i--;) { // initialise with 03269 OrderArray[i] = 0;3270 MaxArray[i] = 0;3271 }3272 while (!file.eof()) { // parse from file3273 AtomNr = -1;3274 file >> AtomNr;3275 if (AtomNr != -1) {// test whether we really parsed something (this is necessary, otherwise last atom is set twice and to 0 on second time)3276 file >> value;3277 OrderArray[AtomNr] = value;3278 file >> value;3279 MaxArray[AtomNr] = value;3280 //*out << Verbose(2) << "AtomNr " << AtomNr << " with order " << (int)OrderArray[AtomNr] << " and max order set to " << (int)MaxArray[AtomNr] << "." << endl;3281 }3282 }3283 atom *Walker = start;3284 while (Walker->next != end) { // fill into atom classes3285 Walker = Walker->next;3286 Walker->AdaptiveOrder = OrderArray[Walker->nr];3287 Walker->MaxOrder = MaxArray[Walker->nr];3288 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl;3289 }3290 file.close();3291 *out << Verbose(1) << "done." << endl;3292 status = true;3293 } else {3294 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;3295 status = false;3296 }3297 Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray");3298 Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray");3299 3300 *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl;3301 return status;3255 unsigned char *OrderArray = (unsigned char *) Malloc(sizeof(unsigned char)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 3256 bool *MaxArray = (bool *) Malloc(sizeof(bool)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *MaxArray"); 3257 bool status; 3258 int AtomNr, value; 3259 stringstream line; 3260 ifstream file; 3261 3262 *out << Verbose(1) << "Begin of ParseOrderAtSiteFromFile" << endl; 3263 for(int i=AtomCount;i--;) 3264 OrderArray[i] = 0; 3265 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE; 3266 file.open(line.str().c_str()); 3267 if (file != NULL) { 3268 for (int i=AtomCount;i--;) { // initialise with 0 3269 OrderArray[i] = 0; 3270 MaxArray[i] = 0; 3271 } 3272 while (!file.eof()) { // parse from file 3273 AtomNr = -1; 3274 file >> AtomNr; 3275 if (AtomNr != -1) { // test whether we really parsed something (this is necessary, otherwise last atom is set twice and to 0 on second time) 3276 file >> value; 3277 OrderArray[AtomNr] = value; 3278 file >> value; 3279 MaxArray[AtomNr] = value; 3280 //*out << Verbose(2) << "AtomNr " << AtomNr << " with order " << (int)OrderArray[AtomNr] << " and max order set to " << (int)MaxArray[AtomNr] << "." << endl; 3281 } 3282 } 3283 atom *Walker = start; 3284 while (Walker->next != end) { // fill into atom classes 3285 Walker = Walker->next; 3286 Walker->AdaptiveOrder = OrderArray[Walker->nr]; 3287 Walker->MaxOrder = MaxArray[Walker->nr]; 3288 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl; 3289 } 3290 file.close(); 3291 *out << Verbose(1) << "done." << endl; 3292 status = true; 3293 } else { 3294 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl; 3295 status = false; 3296 } 3297 Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 3298 Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray"); 3299 3300 *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl; 3301 return status; 3302 3302 }; 3303 3303 … … 3310 3310 void molecule::CreateListOfBondsPerAtom(ofstream *out) 3311 3311 { 3312 bond *Binder = NULL;3313 atom *Walker = NULL;3314 int TotalDegree;3315 *out << Verbose(1) << "Begin of Creating ListOfBondsPerAtom: AtomCount = " << AtomCount << "\tBondCount = " << BondCount << "\tNoNonBonds = " << NoNonBonds << "." << endl;3316 3317 // re-allocate memory3318 *out << Verbose(2) << "(Re-)Allocating memory." << endl;3319 if (ListOfBondsPerAtom != NULL) {3320 for(int i=AtomCount;i--;)3321 Free((void **)&ListOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom[i]");3322 Free((void **)&ListOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom");3323 }3324 if (NumberOfBondsPerAtom != NULL)3325 Free((void **)&NumberOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: NumberOfBondsPerAtom");3326 ListOfBondsPerAtom = (bond ***) Malloc(sizeof(bond **)*AtomCount, "molecule::CreateListOfBondsPerAtom: ***ListOfBondsPerAtom");3327 NumberOfBondsPerAtom = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfBondsPerAtom: *NumberOfBondsPerAtom");3328 3329 // reset bond counts per atom3330 for(int i=AtomCount;i--;)3331 NumberOfBondsPerAtom[i] = 0;3332 // count bonds per atom3333 Binder = first;3334 while (Binder->next != last) {3335 Binder = Binder->next;3336 NumberOfBondsPerAtom[Binder->leftatom->nr]++;3337 NumberOfBondsPerAtom[Binder->rightatom->nr]++;3338 }3339 for(int i=AtomCount;i--;) {3340 // allocate list of bonds per atom3341 ListOfBondsPerAtom[i] = (bond **) Malloc(sizeof(bond *)*NumberOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: **ListOfBondsPerAtom[]");3342 // clear the list again, now each NumberOfBondsPerAtom marks current free field3343 NumberOfBondsPerAtom[i] = 0;3344 }3345 // fill the list3346 Binder = first;3347 while (Binder->next != last) {3348 Binder = Binder->next;3349 ListOfBondsPerAtom[Binder->leftatom->nr][NumberOfBondsPerAtom[Binder->leftatom->nr]++] = Binder;3350 ListOfBondsPerAtom[Binder->rightatom->nr][NumberOfBondsPerAtom[Binder->rightatom->nr]++] = Binder;3351 }3352 3353 // output list for debugging3354 *out << Verbose(3) << "ListOfBondsPerAtom for each atom:" << endl;3355 Walker = start;3356 while (Walker->next != end) {3357 Walker = Walker->next;3358 *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: ";3359 TotalDegree = 0;3360 for (int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) {3361 *out << *ListOfBondsPerAtom[Walker->nr][j] << "\t";3362 TotalDegree += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;3363 }3364 *out << " -- TotalDegree: " << TotalDegree << endl;3365 }3366 *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl;3312 bond *Binder = NULL; 3313 atom *Walker = NULL; 3314 int TotalDegree; 3315 *out << Verbose(1) << "Begin of Creating ListOfBondsPerAtom: AtomCount = " << AtomCount << "\tBondCount = " << BondCount << "\tNoNonBonds = " << NoNonBonds << "." << endl; 3316 3317 // re-allocate memory 3318 *out << Verbose(2) << "(Re-)Allocating memory." << endl; 3319 if (ListOfBondsPerAtom != NULL) { 3320 for(int i=AtomCount;i--;) 3321 Free((void **)&ListOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom[i]"); 3322 Free((void **)&ListOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom"); 3323 } 3324 if (NumberOfBondsPerAtom != NULL) 3325 Free((void **)&NumberOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: NumberOfBondsPerAtom"); 3326 ListOfBondsPerAtom = (bond ***) Malloc(sizeof(bond **)*AtomCount, "molecule::CreateListOfBondsPerAtom: ***ListOfBondsPerAtom"); 3327 NumberOfBondsPerAtom = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfBondsPerAtom: *NumberOfBondsPerAtom"); 3328 3329 // reset bond counts per atom 3330 for(int i=AtomCount;i--;) 3331 NumberOfBondsPerAtom[i] = 0; 3332 // count bonds per atom 3333 Binder = first; 3334 while (Binder->next != last) { 3335 Binder = Binder->next; 3336 NumberOfBondsPerAtom[Binder->leftatom->nr]++; 3337 NumberOfBondsPerAtom[Binder->rightatom->nr]++; 3338 } 3339 for(int i=AtomCount;i--;) { 3340 // allocate list of bonds per atom 3341 ListOfBondsPerAtom[i] = (bond **) Malloc(sizeof(bond *)*NumberOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: **ListOfBondsPerAtom[]"); 3342 // clear the list again, now each NumberOfBondsPerAtom marks current free field 3343 NumberOfBondsPerAtom[i] = 0; 3344 } 3345 // fill the list 3346 Binder = first; 3347 while (Binder->next != last) { 3348 Binder = Binder->next; 3349 ListOfBondsPerAtom[Binder->leftatom->nr][NumberOfBondsPerAtom[Binder->leftatom->nr]++] = Binder; 3350 ListOfBondsPerAtom[Binder->rightatom->nr][NumberOfBondsPerAtom[Binder->rightatom->nr]++] = Binder; 3351 } 3352 3353 // output list for debugging 3354 *out << Verbose(3) << "ListOfBondsPerAtom for each atom:" << endl; 3355 Walker = start; 3356 while (Walker->next != end) { 3357 Walker = Walker->next; 3358 *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: "; 3359 TotalDegree = 0; 3360 for (int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) { 3361 *out << *ListOfBondsPerAtom[Walker->nr][j] << "\t"; 3362 TotalDegree += ListOfBondsPerAtom[Walker->nr][j]->BondDegree; 3363 } 3364 *out << " -- TotalDegree: " << TotalDegree << endl; 3365 } 3366 *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl; 3367 3367 }; 3368 3368 … … 3381 3381 void molecule::BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem) 3382 3382 { 3383 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::BreadthFirstSearchAdd: **PredecessorList");3384 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::BreadthFirstSearchAdd: *ShortestPathList");3385 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::BreadthFirstSearchAdd: *ColorList");3386 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);3387 atom *Walker = NULL, *OtherAtom = NULL;3388 bond *Binder = NULL;3389 3390 // add Root if not done yet3391 AtomStack->ClearStack();3392 if (AddedAtomList[Root->nr] == NULL)// add Root if not yet present3393 AddedAtomList[Root->nr] = Mol->AddCopyAtom(Root);3394 AtomStack->Push(Root);3395 3396 // initialise each vertex as white with no predecessor, empty queue, color Root lightgray3397 for (int i=AtomCount;i--;) {3398 PredecessorList[i] = NULL;3399 ShortestPathList[i] = -1;3400 if (AddedAtomList[i] != NULL) // mark already present atoms (i.e. Root and maybe others) as visited3401 ColorList[i] = lightgray;3402 else3403 ColorList[i] = white;3404 }3405 ShortestPathList[Root->nr] = 0;3406 3407 // and go on ... Queue always contains all lightgray vertices3408 while (!AtomStack->IsEmpty()) {3409 // we have to pop the oldest atom from stack. This keeps the atoms on the stack always of the same ShortestPath distance.3410 // 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 again3411 // append length of 3 (their neighbours). Thus on stack we have always atoms of a certain length n at bottom of stack and3412 // followed by n+1 till top of stack.3413 Walker = AtomStack->PopFirst(); // pop oldest added3414 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl;3415 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {3416 Binder = ListOfBondsPerAtom[Walker->nr][i];3417 if (Binder != NULL) { // don't look at bond equal NULL3418 OtherAtom = Binder->GetOtherAtom(Walker);3419 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;3420 if (ColorList[OtherAtom->nr] == white) {3421 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)3422 ColorList[OtherAtom->nr] = lightgray;3423 PredecessorList[OtherAtom->nr] = Walker;// Walker is the predecessor3424 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;3425 *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;3426 if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance3427 *out << Verbose(3);3428 if (AddedAtomList[OtherAtom->nr] == NULL) { // add if it's not been so far3429 AddedAtomList[OtherAtom->nr] = Mol->AddCopyAtom(OtherAtom);3430 *out << "Added OtherAtom " << OtherAtom->Name;3431 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);3432 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;3433 AddedBondList[Binder->nr]->Type = Binder->Type;3434 *out << " and bond " << *(AddedBondList[Binder->nr]) << ", ";3435 } 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)3436 *out << "Not adding OtherAtom " << OtherAtom->Name;3437 if (AddedBondList[Binder->nr] == NULL) {3438 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);3439 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;3440 AddedBondList[Binder->nr]->Type = Binder->Type;3441 *out << ", added Bond " << *(AddedBondList[Binder->nr]);3442 } else3443 *out << ", not added Bond ";3444 }3445 *out << ", putting OtherAtom into queue." << endl;3446 AtomStack->Push(OtherAtom);3447 } else { // out of bond order, then replace3448 if ((AddedAtomList[OtherAtom->nr] == NULL) && (Binder->Cyclic))3449 ColorList[OtherAtom->nr] = white; // unmark if it has not been queued/added, to make it available via its other bonds (cyclic)3450 if (Binder == Bond)3451 *out << Verbose(3) << "Not Queueing, is the Root bond";3452 else if (ShortestPathList[OtherAtom->nr] >= BondOrder)3453 *out << Verbose(3) << "Not Queueing, is out of Bond Count of " << BondOrder;3454 if (!Binder->Cyclic)3455 *out << ", is not part of a cyclic bond, saturating bond with Hydrogen." << endl;3456 if (AddedBondList[Binder->nr] == NULL) {3457 if ((AddedAtomList[OtherAtom->nr] != NULL)) { // .. whether we add or saturate3458 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);3459 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;3460 AddedBondList[Binder->nr]->Type = Binder->Type;3461 } else {3383 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::BreadthFirstSearchAdd: **PredecessorList"); 3384 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::BreadthFirstSearchAdd: *ShortestPathList"); 3385 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::BreadthFirstSearchAdd: *ColorList"); 3386 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount); 3387 atom *Walker = NULL, *OtherAtom = NULL; 3388 bond *Binder = NULL; 3389 3390 // add Root if not done yet 3391 AtomStack->ClearStack(); 3392 if (AddedAtomList[Root->nr] == NULL) // add Root if not yet present 3393 AddedAtomList[Root->nr] = Mol->AddCopyAtom(Root); 3394 AtomStack->Push(Root); 3395 3396 // initialise each vertex as white with no predecessor, empty queue, color Root lightgray 3397 for (int i=AtomCount;i--;) { 3398 PredecessorList[i] = NULL; 3399 ShortestPathList[i] = -1; 3400 if (AddedAtomList[i] != NULL) // mark already present atoms (i.e. Root and maybe others) as visited 3401 ColorList[i] = lightgray; 3402 else 3403 ColorList[i] = white; 3404 } 3405 ShortestPathList[Root->nr] = 0; 3406 3407 // and go on ... Queue always contains all lightgray vertices 3408 while (!AtomStack->IsEmpty()) { 3409 // we have to pop the oldest atom from stack. This keeps the atoms on the stack always of the same ShortestPath distance. 3410 // 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 3411 // append length of 3 (their neighbours). Thus on stack we have always atoms of a certain length n at bottom of stack and 3412 // followed by n+1 till top of stack. 3413 Walker = AtomStack->PopFirst(); // pop oldest added 3414 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl; 3415 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 3416 Binder = ListOfBondsPerAtom[Walker->nr][i]; 3417 if (Binder != NULL) { // don't look at bond equal NULL 3418 OtherAtom = Binder->GetOtherAtom(Walker); 3419 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 3420 if (ColorList[OtherAtom->nr] == white) { 3421 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) 3422 ColorList[OtherAtom->nr] = lightgray; 3423 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 3424 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 3425 *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; 3426 if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance 3427 *out << Verbose(3); 3428 if (AddedAtomList[OtherAtom->nr] == NULL) { // add if it's not been so far 3429 AddedAtomList[OtherAtom->nr] = Mol->AddCopyAtom(OtherAtom); 3430 *out << "Added OtherAtom " << OtherAtom->Name; 3431 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3432 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3433 AddedBondList[Binder->nr]->Type = Binder->Type; 3434 *out << " and bond " << *(AddedBondList[Binder->nr]) << ", "; 3435 } 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) 3436 *out << "Not adding OtherAtom " << OtherAtom->Name; 3437 if (AddedBondList[Binder->nr] == NULL) { 3438 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3439 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3440 AddedBondList[Binder->nr]->Type = Binder->Type; 3441 *out << ", added Bond " << *(AddedBondList[Binder->nr]); 3442 } else 3443 *out << ", not added Bond "; 3444 } 3445 *out << ", putting OtherAtom into queue." << endl; 3446 AtomStack->Push(OtherAtom); 3447 } else { // out of bond order, then replace 3448 if ((AddedAtomList[OtherAtom->nr] == NULL) && (Binder->Cyclic)) 3449 ColorList[OtherAtom->nr] = white; // unmark if it has not been queued/added, to make it available via its other bonds (cyclic) 3450 if (Binder == Bond) 3451 *out << Verbose(3) << "Not Queueing, is the Root bond"; 3452 else if (ShortestPathList[OtherAtom->nr] >= BondOrder) 3453 *out << Verbose(3) << "Not Queueing, is out of Bond Count of " << BondOrder; 3454 if (!Binder->Cyclic) 3455 *out << ", is not part of a cyclic bond, saturating bond with Hydrogen." << endl; 3456 if (AddedBondList[Binder->nr] == NULL) { 3457 if ((AddedAtomList[OtherAtom->nr] != NULL)) { // .. whether we add or saturate 3458 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3459 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3460 AddedBondList[Binder->nr]->Type = Binder->Type; 3461 } else { 3462 3462 #ifdef ADDHYDROGEN 3463 if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))3464 exit(1);3463 if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem)) 3464 exit(1); 3465 3465 #endif 3466 }3467 }3468 }3469 } else {3470 *out << Verbose(3) << "Not Adding, has already been visited." << endl;3471 // This has to be a cyclic bond, check whether it's present ...3472 if (AddedBondList[Binder->nr] == NULL) {3473 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) {3474 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);3475 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;3476 AddedBondList[Binder->nr]->Type = Binder->Type;3477 } else { // if it's root bond it has to broken (otherwise we would not create the fragments)3466 } 3467 } 3468 } 3469 } else { 3470 *out << Verbose(3) << "Not Adding, has already been visited." << endl; 3471 // This has to be a cyclic bond, check whether it's present ... 3472 if (AddedBondList[Binder->nr] == NULL) { 3473 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 3474 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3475 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3476 AddedBondList[Binder->nr]->Type = Binder->Type; 3477 } else { // if it's root bond it has to broken (otherwise we would not create the fragments) 3478 3478 #ifdef ADDHYDROGEN 3479 if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))3480 exit(1);3479 if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem)) 3480 exit(1); 3481 3481 #endif 3482 }3483 }3484 }3485 }3486 }3487 ColorList[Walker->nr] = black;3488 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;3489 }3490 Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList");3491 Free((void **)&ShortestPathList, "molecule::BreadthFirstSearchAdd: **ShortestPathList");3492 Free((void **)&ColorList, "molecule::BreadthFirstSearchAdd: **ColorList");3493 delete(AtomStack);3482 } 3483 } 3484 } 3485 } 3486 } 3487 ColorList[Walker->nr] = black; 3488 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 3489 } 3490 Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList"); 3491 Free((void **)&ShortestPathList, "molecule::BreadthFirstSearchAdd: **ShortestPathList"); 3492 Free((void **)&ColorList, "molecule::BreadthFirstSearchAdd: **ColorList"); 3493 delete(AtomStack); 3494 3494 }; 3495 3495 … … 3505 3505 bool molecule::BuildInducedSubgraph(ofstream *out, const molecule *Father) 3506 3506 { 3507 atom *Walker = NULL, *OtherAtom = NULL;3508 bool status = true;3509 atom **ParentList = (atom **) Malloc(sizeof(atom *)*Father->AtomCount, "molecule::BuildInducedSubgraph: **ParentList");3510 3511 *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl;3512 3513 // reset parent list3514 *out << Verbose(3) << "Resetting ParentList." << endl;3515 for (int i=Father->AtomCount;i--;)3516 ParentList[i] = NULL;3517 3518 // fill parent list with sons3519 *out << Verbose(3) << "Filling Parent List." << endl;3520 Walker = start;3521 while (Walker->next != end) {3522 Walker = Walker->next;3523 ParentList[Walker->father->nr] = Walker;3524 // Outputting List for debugging3525 *out << Verbose(4) << "Son["<< Walker->father->nr <<"] of " << Walker->father <<" is " << ParentList[Walker->father->nr] << "." << endl;3526 }3527 3528 // check each entry of parent list and if ok (one-to-and-onto matching) create bonds3529 *out << Verbose(3) << "Creating bonds." << endl;3530 Walker = Father->start;3531 while (Walker->next != Father->end) {3532 Walker = Walker->next;3533 if (ParentList[Walker->nr] != NULL) {3534 if (ParentList[Walker->nr]->father != Walker) {3535 status = false;3536 } else {3537 for (int i=0;i<Father->NumberOfBondsPerAtom[Walker->nr];i++) {3538 OtherAtom = Father->ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);3539 if (ParentList[OtherAtom->nr] != NULL) { // if otheratom is also a father of an atom on this molecule, create the bond3540 *out << Verbose(4) << "Endpoints of Bond " << Father->ListOfBondsPerAtom[Walker->nr][i] << " are both present: " << ParentList[Walker->nr]->Name << " and " << ParentList[OtherAtom->nr]->Name << "." << endl;3541 AddBond(ParentList[Walker->nr], ParentList[OtherAtom->nr], Father->ListOfBondsPerAtom[Walker->nr][i]->BondDegree);3542 }3543 }3544 }3545 }3546 }3547 3548 Free((void **)&ParentList, "molecule::BuildInducedSubgraph: **ParentList");3549 *out << Verbose(2) << "End of BuildInducedSubgraph." << endl;3550 return status;3507 atom *Walker = NULL, *OtherAtom = NULL; 3508 bool status = true; 3509 atom **ParentList = (atom **) Malloc(sizeof(atom *)*Father->AtomCount, "molecule::BuildInducedSubgraph: **ParentList"); 3510 3511 *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl; 3512 3513 // reset parent list 3514 *out << Verbose(3) << "Resetting ParentList." << endl; 3515 for (int i=Father->AtomCount;i--;) 3516 ParentList[i] = NULL; 3517 3518 // fill parent list with sons 3519 *out << Verbose(3) << "Filling Parent List." << endl; 3520 Walker = start; 3521 while (Walker->next != end) { 3522 Walker = Walker->next; 3523 ParentList[Walker->father->nr] = Walker; 3524 // Outputting List for debugging 3525 *out << Verbose(4) << "Son["<< Walker->father->nr <<"] of " << Walker->father << " is " << ParentList[Walker->father->nr] << "." << endl; 3526 } 3527 3528 // check each entry of parent list and if ok (one-to-and-onto matching) create bonds 3529 *out << Verbose(3) << "Creating bonds." << endl; 3530 Walker = Father->start; 3531 while (Walker->next != Father->end) { 3532 Walker = Walker->next; 3533 if (ParentList[Walker->nr] != NULL) { 3534 if (ParentList[Walker->nr]->father != Walker) { 3535 status = false; 3536 } else { 3537 for (int i=0;i<Father->NumberOfBondsPerAtom[Walker->nr];i++) { 3538 OtherAtom = Father->ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 3539 if (ParentList[OtherAtom->nr] != NULL) { // if otheratom is also a father of an atom on this molecule, create the bond 3540 *out << Verbose(4) << "Endpoints of Bond " << Father->ListOfBondsPerAtom[Walker->nr][i] << " are both present: " << ParentList[Walker->nr]->Name << " and " << ParentList[OtherAtom->nr]->Name << "." << endl; 3541 AddBond(ParentList[Walker->nr], ParentList[OtherAtom->nr], Father->ListOfBondsPerAtom[Walker->nr][i]->BondDegree); 3542 } 3543 } 3544 } 3545 } 3546 } 3547 3548 Free((void **)&ParentList, "molecule::BuildInducedSubgraph: **ParentList"); 3549 *out << Verbose(2) << "End of BuildInducedSubgraph." << endl; 3550 return status; 3551 3551 }; 3552 3552 … … 3560 3560 int molecule::LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList) 3561 3561 { 3562 atom *Runner = NULL;3563 int SP, Removal;3564 3565 *out << Verbose(2) << "Looking for removal candidate." << endl;3566 SP = -1; //0;// not -1, so that Root is never removed3567 Removal = -1;3568 for (KeySet::iterator runner = Leaf->begin(); runner != Leaf->end(); runner++) {3569 Runner = FindAtom((*runner));3570 if (Runner->type->Z != 1) { // skip all those added hydrogens when re-filling snake stack3571 if (ShortestPathList[(*runner)] > SP) {// remove the oldest one with longest shortest path3572 SP = ShortestPathList[(*runner)];3573 Removal = (*runner);3574 }3575 }3576 }3577 return Removal;3562 atom *Runner = NULL; 3563 int SP, Removal; 3564 3565 *out << Verbose(2) << "Looking for removal candidate." << endl; 3566 SP = -1; //0; // not -1, so that Root is never removed 3567 Removal = -1; 3568 for (KeySet::iterator runner = Leaf->begin(); runner != Leaf->end(); runner++) { 3569 Runner = FindAtom((*runner)); 3570 if (Runner->type->Z != 1) { // skip all those added hydrogens when re-filling snake stack 3571 if (ShortestPathList[(*runner)] > SP) { // remove the oldest one with longest shortest path 3572 SP = ShortestPathList[(*runner)]; 3573 Removal = (*runner); 3574 } 3575 } 3576 } 3577 return Removal; 3578 3578 }; 3579 3579 … … 3588 3588 molecule * molecule::StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem) 3589 3589 { 3590 atom *Runner = NULL, *FatherOfRunner = NULL, *OtherFather = NULL;3591 atom **SonList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::StoreFragmentFromStack: **SonList");3592 molecule *Leaf = new molecule(elemente);3593 bool LonelyFlag = false;3594 int size;3595 3596 // *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl;3597 3598 Leaf->BondDistance = BondDistance;3599 for(int i=NDIM*2;i--;)3600 Leaf->cell_size[i] = cell_size[i];3601 3602 // initialise SonList (indicates when we need to replace a bond with hydrogen instead)3603 for(int i=AtomCount;i--;)3604 SonList[i] = NULL;3605 3606 // first create the minimal set of atoms from the KeySet3607 size = 0;3608 for(KeySet::iterator runner = Leaflet.begin(); runner != Leaflet.end(); runner++) {3609 FatherOfRunner = FindAtom((*runner));// find the id3610 SonList[FatherOfRunner->nr] = Leaf->AddCopyAtom(FatherOfRunner);3611 size++;3612 }3613 3614 // create the bonds between all: Make it an induced subgraph and add hydrogen3615 // *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl;3616 Runner = Leaf->start;3617 while (Runner->next != Leaf->end) {3618 Runner = Runner->next;3619 LonelyFlag = true;3620 FatherOfRunner = Runner->father;3621 if (SonList[FatherOfRunner->nr] != NULL) {// check if this, our father, is present in list3622 // create all bonds3623 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father3624 OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner);3625 // *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather;3626 if (SonList[OtherFather->nr] != NULL) {3627 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl;3628 if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba)3629 // *out << Verbose(3) << "Adding Bond: ";3630 // *out <<3631 Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree);3632 // *out << "." << endl;3633 //NumBonds[Runner->nr]++;3634 } else {3635 // *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl;3636 }3637 LonelyFlag = false;3638 } else {3639 // *out << ", who has no son in this fragment molecule." << endl;3590 atom *Runner = NULL, *FatherOfRunner = NULL, *OtherFather = NULL; 3591 atom **SonList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::StoreFragmentFromStack: **SonList"); 3592 molecule *Leaf = new molecule(elemente); 3593 bool LonelyFlag = false; 3594 int size; 3595 3596 // *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl; 3597 3598 Leaf->BondDistance = BondDistance; 3599 for(int i=NDIM*2;i--;) 3600 Leaf->cell_size[i] = cell_size[i]; 3601 3602 // initialise SonList (indicates when we need to replace a bond with hydrogen instead) 3603 for(int i=AtomCount;i--;) 3604 SonList[i] = NULL; 3605 3606 // first create the minimal set of atoms from the KeySet 3607 size = 0; 3608 for(KeySet::iterator runner = Leaflet.begin(); runner != Leaflet.end(); runner++) { 3609 FatherOfRunner = FindAtom((*runner)); // find the id 3610 SonList[FatherOfRunner->nr] = Leaf->AddCopyAtom(FatherOfRunner); 3611 size++; 3612 } 3613 3614 // create the bonds between all: Make it an induced subgraph and add hydrogen 3615 // *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl; 3616 Runner = Leaf->start; 3617 while (Runner->next != Leaf->end) { 3618 Runner = Runner->next; 3619 LonelyFlag = true; 3620 FatherOfRunner = Runner->father; 3621 if (SonList[FatherOfRunner->nr] != NULL) { // check if this, our father, is present in list 3622 // create all bonds 3623 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father 3624 OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner); 3625 // *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather; 3626 if (SonList[OtherFather->nr] != NULL) { 3627 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 3628 if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba) 3629 // *out << Verbose(3) << "Adding Bond: "; 3630 // *out << 3631 Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree); 3632 // *out << "." << endl; 3633 //NumBonds[Runner->nr]++; 3634 } else { 3635 // *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl; 3636 } 3637 LonelyFlag = false; 3638 } else { 3639 // *out << ", who has no son in this fragment molecule." << endl; 3640 3640 #ifdef ADDHYDROGEN 3641 //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl;3642 if(!Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem))3643 exit(1);3641 //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl; 3642 if(!Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem)) 3643 exit(1); 3644 3644 #endif 3645 //NumBonds[Runner->nr] += ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree;3646 }3647 }3648 } else {3649 *out << Verbose(0) << "ERROR: Son " << Runner->Name << " has father " << FatherOfRunner->Name << " but its entry in SonList is " << SonList[FatherOfRunner->nr] << "!" << endl;3650 }3651 if ((LonelyFlag) && (size > 1)) {3652 *out << Verbose(0) << *Runner << "has got bonds only to hydrogens!" << endl;3653 }3645 //NumBonds[Runner->nr] += ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree; 3646 } 3647 } 3648 } else { 3649 *out << Verbose(0) << "ERROR: Son " << Runner->Name << " has father " << FatherOfRunner->Name << " but its entry in SonList is " << SonList[FatherOfRunner->nr] << "!" << endl; 3650 } 3651 if ((LonelyFlag) && (size > 1)) { 3652 *out << Verbose(0) << *Runner << "has got bonds only to hydrogens!" << endl; 3653 } 3654 3654 #ifdef ADDHYDROGEN 3655 while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen3656 Runner = Runner->next;3655 while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen 3656 Runner = Runner->next; 3657 3657 #endif 3658 }3659 Leaf->CreateListOfBondsPerAtom(out);3660 //Leaflet->Leaf->ScanForPeriodicCorrection(out);3661 Free((void **)&SonList, "molecule::StoreFragmentFromStack: **SonList");3662 // *out << Verbose(1) << "End of StoreFragmentFromKeyset." << endl;3663 return Leaf;3658 } 3659 Leaf->CreateListOfBondsPerAtom(out); 3660 //Leaflet->Leaf->ScanForPeriodicCorrection(out); 3661 Free((void **)&SonList, "molecule::StoreFragmentFromStack: **SonList"); 3662 // *out << Verbose(1) << "End of StoreFragmentFromKeyset." << endl; 3663 return Leaf; 3664 3664 }; 3665 3665 … … 3667 3667 */ 3668 3668 struct UniqueFragments { 3669 config *configuration;3670 atom *Root;3671 Graph *Leaflet;3672 KeySet *FragmentSet;3673 int ANOVAOrder;3674 int FragmentCounter;3675 int CurrentIndex;3676 double TEFactor;3677 int *ShortestPathList;3678 bool **UsedList;3679 bond **BondsPerSPList;3680 int *BondsPerSPCount;3669 config *configuration; 3670 atom *Root; 3671 Graph *Leaflet; 3672 KeySet *FragmentSet; 3673 int ANOVAOrder; 3674 int FragmentCounter; 3675 int CurrentIndex; 3676 double TEFactor; 3677 int *ShortestPathList; 3678 bool **UsedList; 3679 bond **BondsPerSPList; 3680 int *BondsPerSPCount; 3681 3681 }; 3682 3682 3683 3683 /** From a given set of Bond sorted by Shortest Path distance, create all possible fragments of size \a SetDimension. 3684 3684 * -# loops over every possible combination (2^dimension of edge set) 3685 * -# inserts current set, if there's still space left3686 * -# yes: calls SPFragmentGenerator with structure, created new edge list and size respective to root dist3685 * -# inserts current set, if there's still space left 3686 * -# yes: calls SPFragmentGenerator with structure, created new edge list and size respective to root dist 3687 3687 ance+1 3688 * -# no: stores fragment into keyset list by calling InsertFragmentIntoGraph3689 * -# removes all items added into the snake stack (in UniqueFragments structure) added during level (root3688 * -# no: stores fragment into keyset list by calling InsertFragmentIntoGraph 3689 * -# removes all items added into the snake stack (in UniqueFragments structure) added during level (root 3690 3690 distance) and current set 3691 3691 * \param *out output stream for debugging … … 3697 3697 void molecule::SPFragmentGenerator(ofstream *out, struct UniqueFragments *FragmentSearch, int RootDistance, bond **BondsSet, int SetDimension, int SubOrder) 3698 3698 { 3699 atom *OtherWalker = NULL;3700 int verbosity = 0; //FragmentSearch->ANOVAOrder-SubOrder;3701 int NumCombinations;3702 bool bit;3703 int bits, TouchedIndex, SubSetDimension, SP, Added;3704 int Removal;3705 int SpaceLeft;3706 int *TouchedList = (int *) Malloc(sizeof(int)*(SubOrder+1), "molecule::SPFragmentGenerator: *TouchedList");3707 bond *Binder = NULL;3708 bond **BondsList = NULL;3709 KeySetTestPair TestKeySetInsert;3710 3711 NumCombinations = 1 << SetDimension;3712 3713 // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen3714 // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder3715 // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden3716 3717 *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl;3718 *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;3719 3720 // initialised touched list (stores added atoms on this level)3721 *out << Verbose(1+verbosity) << "Clearing touched list." << endl;3722 for (TouchedIndex=SubOrder+1;TouchedIndex--;)// empty touched list3723 TouchedList[TouchedIndex] = -1;3724 TouchedIndex = 0;3725 3726 // create every possible combination of the endpieces3727 *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl;3728 for (int i=1;i<NumCombinations;i++) {// sweep through all power set combinations (skip empty set!)3729 // count the set bit of i3730 bits = 0;3731 for (int j=SetDimension;j--;)3732 bits += (i & (1 << j)) >> j;3733 3734 *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl;3735 if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue3736 // --1-- add this set of the power set of bond partners to the snake stack3737 Added = 0;3738 for (int j=0;j<SetDimension;j++) {// pull out every bit by shifting3739 bit = ((i & (1 << j)) != 0);// mask the bit for the j-th bond3740 if (bit) {// if bit is set, we add this bond partner3741 OtherWalker = BondsSet[j]->rightatom;// rightatom is always the one more distant, i.e. the one to add3742 //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl;3743 *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl;3744 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr);3745 if (TestKeySetInsert.second) {3746 TouchedList[TouchedIndex++] = OtherWalker->nr;// note as added3747 Added++;3748 } else {3749 *out << Verbose(2+verbosity) << "This was item was already present in the keyset." << endl;3750 }3751 //FragmentSearch->UsedList[OtherWalker->nr][i] = true;3752 //}3753 } else {3754 *out << Verbose(2+verbosity) << "Not adding." << endl;3755 }3756 }3757 3758 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore3759 if (SpaceLeft > 0) {3760 *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl;3761 if (SubOrder > 1) {// Due to Added above we have to check extra whether we're not already reaching beyond the desired Order3762 // --2-- look at all added end pieces of this combination, construct bond subsets and sweep through a power set of these by recursion3763 SP = RootDistance+1;// this is the next level3764 // first count the members in the subset3765 SubSetDimension = 0;3766 Binder = FragmentSearch->BondsPerSPList[2*SP];// start node for this level3767 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) {// compare to end node of this level3768 Binder = Binder->next;3769 for (int k=TouchedIndex;k--;) {3770 if (Binder->Contains(TouchedList[k]))// if we added this very endpiece3771 SubSetDimension++;3772 }3773 }3774 // then allocate and fill the list3775 BondsList = (bond **) Malloc(sizeof(bond *)*SubSetDimension, "molecule::SPFragmentGenerator: **BondsList");3776 SubSetDimension = 0;3777 Binder = FragmentSearch->BondsPerSPList[2*SP];3778 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) {3779 Binder = Binder->next;3780 for (int k=0;k<TouchedIndex;k++) {3781 if (Binder->leftatom->nr == TouchedList[k])// leftatom is always the close one3782 BondsList[SubSetDimension++] = Binder;3783 }3784 }3785 *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl;3786 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits);3787 Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList");3788 }3789 } else {3790 // --2-- otherwise store the complete fragment3791 *out << Verbose(1+verbosity) << "Enough items on stack for a fragment!" << endl;3792 // store fragment as a KeySet3793 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: ";3794 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++)3795 *out << (*runner) << " ";3796 *out << endl;3797 //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet))3798 //*out << Verbose(0) << "ERROR: The found fragment is not a connected subgraph!" << endl;3799 InsertFragmentIntoGraph(out, FragmentSearch);3800 //Removal = LookForRemovalCandidate(out, FragmentSearch->FragmentSet, FragmentSearch->ShortestPathList);3801 //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration);3802 }3803 3804 // --3-- remove all added items in this level from snake stack3805 *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl;3806 for(int j=0;j<TouchedIndex;j++) {3807 Removal = TouchedList[j];3808 *out << Verbose(2+verbosity) << "Removing item nr. " << Removal << " from snake stack." << endl;3809 FragmentSearch->FragmentSet->erase(Removal);3810 TouchedList[j] = -1;3811 }3812 *out << Verbose(2) << "Remaining local nr.s on snake stack are: ";3813 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++)3814 *out << (*runner) << " ";3815 *out << endl;3816 TouchedIndex = 0; // set Index to 0 for list of atoms added on this level3817 } else {3818 *out << Verbose(2+verbosity) << "More atoms to add for this set (" << bits << ") than space left on stack " << SubOrder << ", skipping this set." << endl;3819 }3820 }3821 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList");3822 *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl;3699 atom *OtherWalker = NULL; 3700 int verbosity = 0; //FragmentSearch->ANOVAOrder-SubOrder; 3701 int NumCombinations; 3702 bool bit; 3703 int bits, TouchedIndex, SubSetDimension, SP, Added; 3704 int Removal; 3705 int SpaceLeft; 3706 int *TouchedList = (int *) Malloc(sizeof(int)*(SubOrder+1), "molecule::SPFragmentGenerator: *TouchedList"); 3707 bond *Binder = NULL; 3708 bond **BondsList = NULL; 3709 KeySetTestPair TestKeySetInsert; 3710 3711 NumCombinations = 1 << SetDimension; 3712 3713 // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen 3714 // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder 3715 // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden 3716 3717 *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl; 3718 *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; 3719 3720 // initialised touched list (stores added atoms on this level) 3721 *out << Verbose(1+verbosity) << "Clearing touched list." << endl; 3722 for (TouchedIndex=SubOrder+1;TouchedIndex--;) // empty touched list 3723 TouchedList[TouchedIndex] = -1; 3724 TouchedIndex = 0; 3725 3726 // create every possible combination of the endpieces 3727 *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl; 3728 for (int i=1;i<NumCombinations;i++) { // sweep through all power set combinations (skip empty set!) 3729 // count the set bit of i 3730 bits = 0; 3731 for (int j=SetDimension;j--;) 3732 bits += (i & (1 << j)) >> j; 3733 3734 *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl; 3735 if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue 3736 // --1-- add this set of the power set of bond partners to the snake stack 3737 Added = 0; 3738 for (int j=0;j<SetDimension;j++) { // pull out every bit by shifting 3739 bit = ((i & (1 << j)) != 0); // mask the bit for the j-th bond 3740 if (bit) { // if bit is set, we add this bond partner 3741 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add 3742 //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl; 3743 *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl; 3744 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 3745 if (TestKeySetInsert.second) { 3746 TouchedList[TouchedIndex++] = OtherWalker->nr; // note as added 3747 Added++; 3748 } else { 3749 *out << Verbose(2+verbosity) << "This was item was already present in the keyset." << endl; 3750 } 3751 //FragmentSearch->UsedList[OtherWalker->nr][i] = true; 3752 //} 3753 } else { 3754 *out << Verbose(2+verbosity) << "Not adding." << endl; 3755 } 3756 } 3757 3758 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore 3759 if (SpaceLeft > 0) { 3760 *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl; 3761 if (SubOrder > 1) { // Due to Added above we have to check extra whether we're not already reaching beyond the desired Order 3762 // --2-- look at all added end pieces of this combination, construct bond subsets and sweep through a power set of these by recursion 3763 SP = RootDistance+1; // this is the next level 3764 // first count the members in the subset 3765 SubSetDimension = 0; 3766 Binder = FragmentSearch->BondsPerSPList[2*SP]; // start node for this level 3767 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) { // compare to end node of this level 3768 Binder = Binder->next; 3769 for (int k=TouchedIndex;k--;) { 3770 if (Binder->Contains(TouchedList[k])) // if we added this very endpiece 3771 SubSetDimension++; 3772 } 3773 } 3774 // then allocate and fill the list 3775 BondsList = (bond **) Malloc(sizeof(bond *)*SubSetDimension, "molecule::SPFragmentGenerator: **BondsList"); 3776 SubSetDimension = 0; 3777 Binder = FragmentSearch->BondsPerSPList[2*SP]; 3778 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) { 3779 Binder = Binder->next; 3780 for (int k=0;k<TouchedIndex;k++) { 3781 if (Binder->leftatom->nr == TouchedList[k]) // leftatom is always the close one 3782 BondsList[SubSetDimension++] = Binder; 3783 } 3784 } 3785 *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl; 3786 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 3787 Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList"); 3788 } 3789 } else { 3790 // --2-- otherwise store the complete fragment 3791 *out << Verbose(1+verbosity) << "Enough items on stack for a fragment!" << endl; 3792 // store fragment as a KeySet 3793 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: "; 3794 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3795 *out << (*runner) << " "; 3796 *out << endl; 3797 //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet)) 3798 //*out << Verbose(0) << "ERROR: The found fragment is not a connected subgraph!" << endl; 3799 InsertFragmentIntoGraph(out, FragmentSearch); 3800 //Removal = LookForRemovalCandidate(out, FragmentSearch->FragmentSet, FragmentSearch->ShortestPathList); 3801 //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration); 3802 } 3803 3804 // --3-- remove all added items in this level from snake stack 3805 *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl; 3806 for(int j=0;j<TouchedIndex;j++) { 3807 Removal = TouchedList[j]; 3808 *out << Verbose(2+verbosity) << "Removing item nr. " << Removal << " from snake stack." << endl; 3809 FragmentSearch->FragmentSet->erase(Removal); 3810 TouchedList[j] = -1; 3811 } 3812 *out << Verbose(2) << "Remaining local nr.s on snake stack are: "; 3813 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3814 *out << (*runner) << " "; 3815 *out << endl; 3816 TouchedIndex = 0; // set Index to 0 for list of atoms added on this level 3817 } else { 3818 *out << Verbose(2+verbosity) << "More atoms to add for this set (" << bits << ") than space left on stack " << SubOrder << ", skipping this set." << endl; 3819 } 3820 } 3821 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 3822 *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl; 3823 3823 }; 3824 3824 … … 3831 3831 bool molecule::CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment) 3832 3832 { 3833 atom *Walker = NULL, *Walker2 = NULL;3834 bool BondStatus = false;3835 int size;3836 3837 *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl;3838 *out << Verbose(2) << "Disconnected atom: ";3839 3840 // count number of atoms in graph3841 size = 0;3842 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++)3843 size++;3844 if (size > 1)3845 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) {3846 Walker = FindAtom(*runner);3847 BondStatus = false;3848 for(KeySet::iterator runners = Fragment->begin(); runners != Fragment->end(); runners++) {3849 Walker2 = FindAtom(*runners);3850 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {3851 if (ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker) == Walker2) {3852 BondStatus = true;3853 break;3854 }3855 if (BondStatus)3856 break;3857 }3858 }3859 if (!BondStatus) {3860 *out << (*Walker) << endl;3861 return false;3862 }3863 }3864 else {3865 *out << "none." << endl;3866 return true;3867 }3868 *out << "none." << endl;3869 3870 *out << Verbose(1) << "End of CheckForConnectedSubgraph" << endl;3871 3872 return true;3833 atom *Walker = NULL, *Walker2 = NULL; 3834 bool BondStatus = false; 3835 int size; 3836 3837 *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl; 3838 *out << Verbose(2) << "Disconnected atom: "; 3839 3840 // count number of atoms in graph 3841 size = 0; 3842 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) 3843 size++; 3844 if (size > 1) 3845 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) { 3846 Walker = FindAtom(*runner); 3847 BondStatus = false; 3848 for(KeySet::iterator runners = Fragment->begin(); runners != Fragment->end(); runners++) { 3849 Walker2 = FindAtom(*runners); 3850 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) { 3851 if (ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker) == Walker2) { 3852 BondStatus = true; 3853 break; 3854 } 3855 if (BondStatus) 3856 break; 3857 } 3858 } 3859 if (!BondStatus) { 3860 *out << (*Walker) << endl; 3861 return false; 3862 } 3863 } 3864 else { 3865 *out << "none." << endl; 3866 return true; 3867 } 3868 *out << "none." << endl; 3869 3870 *out << Verbose(1) << "End of CheckForConnectedSubgraph" << endl; 3871 3872 return true; 3873 3873 } 3874 3874 … … 3890 3890 int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet) 3891 3891 { 3892 int SP, AtomKeyNr;3893 atom *Walker = NULL, *OtherWalker = NULL, *Predecessor = NULL;3894 bond *Binder = NULL;3895 bond *CurrentEdge = NULL;3896 bond **BondsList = NULL;3897 int RootKeyNr = FragmentSearch.Root->GetTrueFather()->nr;3898 int Counter = FragmentSearch.FragmentCounter;3899 int RemainingWalkers;3900 3901 *out << endl;3902 *out << Verbose(0) << "Begin of PowerSetGenerator with order " << Order << " at Root " << *FragmentSearch.Root << "." << endl;3903 3904 // prepare Label and SP arrays of the BFS search3905 FragmentSearch.ShortestPathList[FragmentSearch.Root->nr] = 0;3906 3907 // prepare root level (SP = 0) and a loop bond denoting Root3908 for (int i=1;i<Order;i++)3909 FragmentSearch.BondsPerSPCount[i] = 0;3910 FragmentSearch.BondsPerSPCount[0] = 1;3911 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root);3912 add(Binder, FragmentSearch.BondsPerSPList[1]);3913 3914 // do a BFS search to fill the SP lists and label the found vertices3915 // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into3916 // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning3917 // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth3918 // (EdgeinSPLevel) of this tree ...3919 // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence3920 // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction.3921 *out << endl;3922 *out << Verbose(0) << "Starting BFS analysis ..." << endl;3923 for (SP = 0; SP < (Order-1); SP++) {3924 *out << Verbose(1) << "New SP level reached: " << SP << ", creating new SP list with " << FragmentSearch.BondsPerSPCount[SP] << " item(s)";3925 if (SP > 0) {3926 *out << ", old level closed with " << FragmentSearch.BondsPerSPCount[SP-1] << " item(s)." << endl;3927 FragmentSearch.BondsPerSPCount[SP] = 0;3928 } else3929 *out << "." << endl;3930 3931 RemainingWalkers = FragmentSearch.BondsPerSPCount[SP];3932 CurrentEdge = FragmentSearch.BondsPerSPList[2*SP];/// start of this SP level's list3933 while (CurrentEdge->next != FragmentSearch.BondsPerSPList[2*SP+1]) {/// end of this SP level's list3934 CurrentEdge = CurrentEdge->next;3935 RemainingWalkers--;3936 Walker = CurrentEdge->rightatom;// rightatom is always the one more distant3937 Predecessor = CurrentEdge->leftatom;// ... and leftatom is predecessor3938 AtomKeyNr = Walker->nr;3939 *out << Verbose(0) << "Current Walker is: " << *Walker << " with nr " << Walker->nr << " and SP of " << SP << ", with " << RemainingWalkers << " remaining walkers on this level." << endl;3940 // check for new sp level3941 // go through all its bonds3942 *out << Verbose(1) << "Going through all bonds of Walker." << endl;3943 for (int i=0;i<NumberOfBondsPerAtom[AtomKeyNr];i++) {3944 Binder = ListOfBondsPerAtom[AtomKeyNr][i];3945 OtherWalker = Binder->GetOtherAtom(Walker);3946 if ((RestrictedKeySet.find(OtherWalker->nr) != RestrictedKeySet.end())3947 #ifdef ADDHYDROGEN3948 && (OtherWalker->type->Z != 1)3949 #endif3950 ) {// skip hydrogens and restrict to fragment3951 *out << Verbose(2) << "Current partner is " << *OtherWalker << " with nr " << OtherWalker->nr << " in bond " << *Binder << "." << endl;3952 // set the label if not set (and push on root stack as well)3953 if ((OtherWalker != Predecessor) && (OtherWalker->GetTrueFather()->nr > RootKeyNr)) { // only pass through those with label bigger than Root's3954 FragmentSearch.ShortestPathList[OtherWalker->nr] = SP+1;3955 *out << Verbose(3) << "Set Shortest Path to " << FragmentSearch.ShortestPathList[OtherWalker->nr] << "." << endl;3956 // add the bond in between to the SP list3957 Binder = new bond(Walker, OtherWalker); // create a new bond in such a manner, that bond::rightatom is always the one more distant3958 add(Binder, FragmentSearch.BondsPerSPList[2*(SP+1)+1]);3959 FragmentSearch.BondsPerSPCount[SP+1]++;3960 *out << Verbose(3) << "Added its bond to SP list, having now " << FragmentSearch.BondsPerSPCount[SP+1] << " item(s)." << endl;3961 } else {3962 if (OtherWalker != Predecessor)3963 *out << Verbose(3) << "Not passing on, as index of " << *OtherWalker << " " << OtherWalker->GetTrueFather()->nr << " is smaller than that of Root " << RootKeyNr << "." << endl;3964 else3965 *out << Verbose(3) << "This is my predecessor " << *Predecessor << "." << endl;3966 }3967 } else *out << Verbose(2) << "Is not in the restricted keyset or skipping hydrogen " << *OtherWalker << "." << endl;3968 }3969 }3970 }3971 3972 // outputting all list for debugging3973 *out << Verbose(0) << "Printing all found lists." << endl;3974 for(int i=1;i<Order;i++) {// skip the root edge in the printing3975 Binder = FragmentSearch.BondsPerSPList[2*i];3976 *out << Verbose(1) << "Current SP level is " << i << "." << endl;3977 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {3978 Binder = Binder->next;3979 *out << Verbose(2) << *Binder << endl;3980 }3981 }3982 3983 // creating fragments with the found edge sets(may be done in reverse order, faster)3984 SP = -1;// the Root <-> Root edge must be subtracted!3985 for(int i=Order;i--;) { // sum up all found edges3986 Binder = FragmentSearch.BondsPerSPList[2*i];3987 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {3988 Binder = Binder->next;3989 SP ++;3990 }3991 }3992 *out << Verbose(0) << "Total number of edges is " << SP << "." << endl;3993 if (SP >= (Order-1)) {3994 // start with root (push on fragment stack)3995 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl;3996 FragmentSearch.FragmentSet->clear();3997 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl;3998 // prepare the subset and call the generator3999 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList");4000 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next;// on SP level 0 there's only the root bond4001 4002 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order);4003 4004 Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList");4005 } else {4006 *out << Verbose(0) << "Not enough total number of edges to build " << Order << "-body fragments." << endl;4007 }4008 4009 // as FragmentSearch structure is used only once, we don't have to clean it anymore4010 // remove root from stack4011 *out << Verbose(0) << "Removing root again from stack." << endl;4012 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr);4013 4014 // free'ing the bonds lists4015 *out << Verbose(0) << "Free'ing all found lists. and resetting index lists" << endl;4016 for(int i=Order;i--;) {4017 *out << Verbose(1) << "Current SP level is " << i << ": ";4018 Binder = FragmentSearch.BondsPerSPList[2*i];4019 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {4020 Binder = Binder->next;4021 // *out << "Removing atom " << Binder->leftatom->nr << " and " << Binder->rightatom->nr << "." << endl; // make sure numbers are local4022 FragmentSearch.ShortestPathList[Binder->leftatom->nr] = -1;4023 FragmentSearch.ShortestPathList[Binder->rightatom->nr] = -1;4024 }4025 // delete added bonds4026 cleanup(FragmentSearch.BondsPerSPList[2*i], FragmentSearch.BondsPerSPList[2*i+1]);4027 // also start and end node4028 *out << "cleaned." << endl;4029 }4030 4031 // return list4032 *out << Verbose(0) << "End of PowerSetGenerator." << endl;4033 return (FragmentSearch.FragmentCounter - Counter);3892 int SP, AtomKeyNr; 3893 atom *Walker = NULL, *OtherWalker = NULL, *Predecessor = NULL; 3894 bond *Binder = NULL; 3895 bond *CurrentEdge = NULL; 3896 bond **BondsList = NULL; 3897 int RootKeyNr = FragmentSearch.Root->GetTrueFather()->nr; 3898 int Counter = FragmentSearch.FragmentCounter; 3899 int RemainingWalkers; 3900 3901 *out << endl; 3902 *out << Verbose(0) << "Begin of PowerSetGenerator with order " << Order << " at Root " << *FragmentSearch.Root << "." << endl; 3903 3904 // prepare Label and SP arrays of the BFS search 3905 FragmentSearch.ShortestPathList[FragmentSearch.Root->nr] = 0; 3906 3907 // prepare root level (SP = 0) and a loop bond denoting Root 3908 for (int i=1;i<Order;i++) 3909 FragmentSearch.BondsPerSPCount[i] = 0; 3910 FragmentSearch.BondsPerSPCount[0] = 1; 3911 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 3912 add(Binder, FragmentSearch.BondsPerSPList[1]); 3913 3914 // do a BFS search to fill the SP lists and label the found vertices 3915 // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into 3916 // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning 3917 // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth 3918 // (EdgeinSPLevel) of this tree ... 3919 // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence 3920 // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction. 3921 *out << endl; 3922 *out << Verbose(0) << "Starting BFS analysis ..." << endl; 3923 for (SP = 0; SP < (Order-1); SP++) { 3924 *out << Verbose(1) << "New SP level reached: " << SP << ", creating new SP list with " << FragmentSearch.BondsPerSPCount[SP] << " item(s)"; 3925 if (SP > 0) { 3926 *out << ", old level closed with " << FragmentSearch.BondsPerSPCount[SP-1] << " item(s)." << endl; 3927 FragmentSearch.BondsPerSPCount[SP] = 0; 3928 } else 3929 *out << "." << endl; 3930 3931 RemainingWalkers = FragmentSearch.BondsPerSPCount[SP]; 3932 CurrentEdge = FragmentSearch.BondsPerSPList[2*SP]; /// start of this SP level's list 3933 while (CurrentEdge->next != FragmentSearch.BondsPerSPList[2*SP+1]) { /// end of this SP level's list 3934 CurrentEdge = CurrentEdge->next; 3935 RemainingWalkers--; 3936 Walker = CurrentEdge->rightatom; // rightatom is always the one more distant 3937 Predecessor = CurrentEdge->leftatom; // ... and leftatom is predecessor 3938 AtomKeyNr = Walker->nr; 3939 *out << Verbose(0) << "Current Walker is: " << *Walker << " with nr " << Walker->nr << " and SP of " << SP << ", with " << RemainingWalkers << " remaining walkers on this level." << endl; 3940 // check for new sp level 3941 // go through all its bonds 3942 *out << Verbose(1) << "Going through all bonds of Walker." << endl; 3943 for (int i=0;i<NumberOfBondsPerAtom[AtomKeyNr];i++) { 3944 Binder = ListOfBondsPerAtom[AtomKeyNr][i]; 3945 OtherWalker = Binder->GetOtherAtom(Walker); 3946 if ((RestrictedKeySet.find(OtherWalker->nr) != RestrictedKeySet.end()) 3947 #ifdef ADDHYDROGEN 3948 && (OtherWalker->type->Z != 1) 3949 #endif 3950 ) { // skip hydrogens and restrict to fragment 3951 *out << Verbose(2) << "Current partner is " << *OtherWalker << " with nr " << OtherWalker->nr << " in bond " << *Binder << "." << endl; 3952 // set the label if not set (and push on root stack as well) 3953 if ((OtherWalker != Predecessor) && (OtherWalker->GetTrueFather()->nr > RootKeyNr)) { // only pass through those with label bigger than Root's 3954 FragmentSearch.ShortestPathList[OtherWalker->nr] = SP+1; 3955 *out << Verbose(3) << "Set Shortest Path to " << FragmentSearch.ShortestPathList[OtherWalker->nr] << "." << endl; 3956 // add the bond in between to the SP list 3957 Binder = new bond(Walker, OtherWalker); // create a new bond in such a manner, that bond::rightatom is always the one more distant 3958 add(Binder, FragmentSearch.BondsPerSPList[2*(SP+1)+1]); 3959 FragmentSearch.BondsPerSPCount[SP+1]++; 3960 *out << Verbose(3) << "Added its bond to SP list, having now " << FragmentSearch.BondsPerSPCount[SP+1] << " item(s)." << endl; 3961 } else { 3962 if (OtherWalker != Predecessor) 3963 *out << Verbose(3) << "Not passing on, as index of " << *OtherWalker << " " << OtherWalker->GetTrueFather()->nr << " is smaller than that of Root " << RootKeyNr << "." << endl; 3964 else 3965 *out << Verbose(3) << "This is my predecessor " << *Predecessor << "." << endl; 3966 } 3967 } else *out << Verbose(2) << "Is not in the restricted keyset or skipping hydrogen " << *OtherWalker << "." << endl; 3968 } 3969 } 3970 } 3971 3972 // outputting all list for debugging 3973 *out << Verbose(0) << "Printing all found lists." << endl; 3974 for(int i=1;i<Order;i++) { // skip the root edge in the printing 3975 Binder = FragmentSearch.BondsPerSPList[2*i]; 3976 *out << Verbose(1) << "Current SP level is " << i << "." << endl; 3977 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 3978 Binder = Binder->next; 3979 *out << Verbose(2) << *Binder << endl; 3980 } 3981 } 3982 3983 // creating fragments with the found edge sets (may be done in reverse order, faster) 3984 SP = -1; // the Root <-> Root edge must be subtracted! 3985 for(int i=Order;i--;) { // sum up all found edges 3986 Binder = FragmentSearch.BondsPerSPList[2*i]; 3987 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 3988 Binder = Binder->next; 3989 SP ++; 3990 } 3991 } 3992 *out << Verbose(0) << "Total number of edges is " << SP << "." << endl; 3993 if (SP >= (Order-1)) { 3994 // start with root (push on fragment stack) 3995 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl; 3996 FragmentSearch.FragmentSet->clear(); 3997 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl; 3998 // prepare the subset and call the generator 3999 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList"); 4000 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next; // on SP level 0 there's only the root bond 4001 4002 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order); 4003 4004 Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList"); 4005 } else { 4006 *out << Verbose(0) << "Not enough total number of edges to build " << Order << "-body fragments." << endl; 4007 } 4008 4009 // as FragmentSearch structure is used only once, we don't have to clean it anymore 4010 // remove root from stack 4011 *out << Verbose(0) << "Removing root again from stack." << endl; 4012 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4013 4014 // free'ing the bonds lists 4015 *out << Verbose(0) << "Free'ing all found lists. and resetting index lists" << endl; 4016 for(int i=Order;i--;) { 4017 *out << Verbose(1) << "Current SP level is " << i << ": "; 4018 Binder = FragmentSearch.BondsPerSPList[2*i]; 4019 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 4020 Binder = Binder->next; 4021 // *out << "Removing atom " << Binder->leftatom->nr << " and " << Binder->rightatom->nr << "." << endl; // make sure numbers are local 4022 FragmentSearch.ShortestPathList[Binder->leftatom->nr] = -1; 4023 FragmentSearch.ShortestPathList[Binder->rightatom->nr] = -1; 4024 } 4025 // delete added bonds 4026 cleanup(FragmentSearch.BondsPerSPList[2*i], FragmentSearch.BondsPerSPList[2*i+1]); 4027 // also start and end node 4028 *out << "cleaned." << endl; 4029 } 4030 4031 // return list 4032 *out << Verbose(0) << "End of PowerSetGenerator." << endl; 4033 return (FragmentSearch.FragmentCounter - Counter); 4034 4034 }; 4035 4035 … … 4042 4042 void molecule::ScanForPeriodicCorrection(ofstream *out) 4043 4043 { 4044 bond *Binder = NULL;4045 bond *OtherBinder = NULL;4046 atom *Walker = NULL;4047 atom *OtherWalker = NULL;4048 double *matrix = ReturnFullMatrixforSymmetric(cell_size);4049 enum Shading *ColorList = NULL;4050 double tmp;4051 Vector Translationvector;4052 //class StackClass<atom *> *CompStack = NULL;4053 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);4054 bool flag = true;4055 4056 *out << Verbose(2) << "Begin of ScanForPeriodicCorrection." << endl;4057 4058 ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::ScanForPeriodicCorrection: *ColorList");4059 while (flag) {4060 // remove bonds that are beyond bonddistance4061 for(int i=NDIM;i--;)4062 Translationvector.x[i] = 0.;4063 // scan all bonds4064 Binder = first;4065 flag = false;4066 while ((!flag) && (Binder->next != last)) {4067 Binder = Binder->next;4068 for (int i=NDIM;i--;) {4069 tmp = fabs(Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]);4070 //*out << Verbose(3) << "Checking " << i << "th distance of " << *Binder->leftatom << " to " << *Binder->rightatom << ": " << tmp << "." << endl;4071 if (tmp > BondDistance) {4072 OtherBinder = Binder->next; // note down binding partner for later re-insertion4073 unlink(Binder);// unlink bond4074 *out << Verbose(2) << "Correcting at bond " << *Binder << "." << endl;4075 flag = true;4076 break;4077 }4078 }4079 }4080 if (flag) {4081 // create translation vector from their periodically modified distance4082 for (int i=NDIM;i--;) {4083 tmp = Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i];4084 if (fabs(tmp) > BondDistance)4085 Translationvector.x[i] = (tmp < 0) ? +1. : -1.;4086 }4087 Translationvector.MatrixMultiplication(matrix);4088 //*out << Verbose(3) << "Translation vector is ";4089 Translationvector.Output(out);4090 *out << endl;4091 // apply to all atoms of first component via BFS4092 for (int i=AtomCount;i--;)4093 ColorList[i] = white;4094 AtomStack->Push(Binder->leftatom);4095 while (!AtomStack->IsEmpty()) {4096 Walker = AtomStack->PopFirst();4097 //*out << Verbose (3) << "Current Walker is: " << *Walker << "." << endl;4098 ColorList[Walker->nr] = black;// mark as explored4099 Walker->x.AddVector(&Translationvector); // translate4100 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {// go through all binding partners4101 if (ListOfBondsPerAtom[Walker->nr][i] != Binder) {4102 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);4103 if (ColorList[OtherWalker->nr] == white) {4104 AtomStack->Push(OtherWalker); // push if yet unexplored4105 }4106 }4107 }4108 }4109 // re-add bond4110 link(Binder, OtherBinder);4111 } else {4112 *out << Verbose(3) << "No corrections for this fragment." << endl;4113 }4114 //delete(CompStack);4115 }4116 4117 // free allocated space from ReturnFullMatrixforSymmetric()4118 delete(AtomStack);4119 Free((void **)&ColorList, "molecule::ScanForPeriodicCorrection: *ColorList");4120 Free((void **)&matrix, "molecule::ScanForPeriodicCorrection: *matrix");4121 *out << Verbose(2) << "End of ScanForPeriodicCorrection." << endl;4044 bond *Binder = NULL; 4045 bond *OtherBinder = NULL; 4046 atom *Walker = NULL; 4047 atom *OtherWalker = NULL; 4048 double *matrix = ReturnFullMatrixforSymmetric(cell_size); 4049 enum Shading *ColorList = NULL; 4050 double tmp; 4051 Vector Translationvector; 4052 //class StackClass<atom *> *CompStack = NULL; 4053 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount); 4054 bool flag = true; 4055 4056 *out << Verbose(2) << "Begin of ScanForPeriodicCorrection." << endl; 4057 4058 ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::ScanForPeriodicCorrection: *ColorList"); 4059 while (flag) { 4060 // remove bonds that are beyond bonddistance 4061 for(int i=NDIM;i--;) 4062 Translationvector.x[i] = 0.; 4063 // scan all bonds 4064 Binder = first; 4065 flag = false; 4066 while ((!flag) && (Binder->next != last)) { 4067 Binder = Binder->next; 4068 for (int i=NDIM;i--;) { 4069 tmp = fabs(Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]); 4070 //*out << Verbose(3) << "Checking " << i << "th distance of " << *Binder->leftatom << " to " << *Binder->rightatom << ": " << tmp << "." << endl; 4071 if (tmp > BondDistance) { 4072 OtherBinder = Binder->next; // note down binding partner for later re-insertion 4073 unlink(Binder); // unlink bond 4074 *out << Verbose(2) << "Correcting at bond " << *Binder << "." << endl; 4075 flag = true; 4076 break; 4077 } 4078 } 4079 } 4080 if (flag) { 4081 // create translation vector from their periodically modified distance 4082 for (int i=NDIM;i--;) { 4083 tmp = Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]; 4084 if (fabs(tmp) > BondDistance) 4085 Translationvector.x[i] = (tmp < 0) ? +1. : -1.; 4086 } 4087 Translationvector.MatrixMultiplication(matrix); 4088 //*out << Verbose(3) << "Translation vector is "; 4089 Translationvector.Output(out); 4090 *out << endl; 4091 // apply to all atoms of first component via BFS 4092 for (int i=AtomCount;i--;) 4093 ColorList[i] = white; 4094 AtomStack->Push(Binder->leftatom); 4095 while (!AtomStack->IsEmpty()) { 4096 Walker = AtomStack->PopFirst(); 4097 //*out << Verbose (3) << "Current Walker is: " << *Walker << "." << endl; 4098 ColorList[Walker->nr] = black; // mark as explored 4099 Walker->x.AddVector(&Translationvector); // translate 4100 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through all binding partners 4101 if (ListOfBondsPerAtom[Walker->nr][i] != Binder) { 4102 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 4103 if (ColorList[OtherWalker->nr] == white) { 4104 AtomStack->Push(OtherWalker); // push if yet unexplored 4105 } 4106 } 4107 } 4108 } 4109 // re-add bond 4110 link(Binder, OtherBinder); 4111 } else { 4112 *out << Verbose(3) << "No corrections for this fragment." << endl; 4113 } 4114 //delete(CompStack); 4115 } 4116 4117 // free allocated space from ReturnFullMatrixforSymmetric() 4118 delete(AtomStack); 4119 Free((void **)&ColorList, "molecule::ScanForPeriodicCorrection: *ColorList"); 4120 Free((void **)&matrix, "molecule::ScanForPeriodicCorrection: *matrix"); 4121 *out << Verbose(2) << "End of ScanForPeriodicCorrection." << endl; 4122 4122 }; 4123 4123 … … 4128 4128 double * molecule::ReturnFullMatrixforSymmetric(double *symm) 4129 4129 { 4130 double *matrix = (double *) Malloc(sizeof(double)*NDIM*NDIM, "molecule::ReturnFullMatrixforSymmetric: *matrix");4131 matrix[0] = symm[0];4132 matrix[1] = symm[1];4133 matrix[2] = symm[3];4134 matrix[3] = symm[1];4135 matrix[4] = symm[2];4136 matrix[5] = symm[4];4137 matrix[6] = symm[3];4138 matrix[7] = symm[4];4139 matrix[8] = symm[5];4140 return matrix;4130 double *matrix = (double *) Malloc(sizeof(double)*NDIM*NDIM, "molecule::ReturnFullMatrixforSymmetric: *matrix"); 4131 matrix[0] = symm[0]; 4132 matrix[1] = symm[1]; 4133 matrix[2] = symm[3]; 4134 matrix[3] = symm[1]; 4135 matrix[4] = symm[2]; 4136 matrix[5] = symm[4]; 4137 matrix[6] = symm[3]; 4138 matrix[7] = symm[4]; 4139 matrix[8] = symm[5]; 4140 return matrix; 4141 4141 }; 4142 4142 4143 4143 bool KeyCompare::operator() (const KeySet SubgraphA, const KeySet SubgraphB) const 4144 4144 { 4145 //cout << "my check is used." << endl;4146 if (SubgraphA.size() < SubgraphB.size()) {4147 return true;4148 } else {4149 if (SubgraphA.size() > SubgraphB.size()) {4150 return false;4151 } else {4152 KeySet::iterator IteratorA = SubgraphA.begin();4153 KeySet::iterator IteratorB = SubgraphB.begin();4154 while ((IteratorA != SubgraphA.end()) && (IteratorB != SubgraphB.end())) {4155 if ((*IteratorA) <(*IteratorB))4156 return true;4157 else if ((*IteratorA) > (*IteratorB)) {4158 return false;4159 } // else, go on to next index4160 IteratorA++;4161 IteratorB++;4162 } // end of while loop4163 }// end of check in case of equal sizes4164 }4165 return false; // if we reach this point, they are equal4145 //cout << "my check is used." << endl; 4146 if (SubgraphA.size() < SubgraphB.size()) { 4147 return true; 4148 } else { 4149 if (SubgraphA.size() > SubgraphB.size()) { 4150 return false; 4151 } else { 4152 KeySet::iterator IteratorA = SubgraphA.begin(); 4153 KeySet::iterator IteratorB = SubgraphB.begin(); 4154 while ((IteratorA != SubgraphA.end()) && (IteratorB != SubgraphB.end())) { 4155 if ((*IteratorA) < (*IteratorB)) 4156 return true; 4157 else if ((*IteratorA) > (*IteratorB)) { 4158 return false; 4159 } // else, go on to next index 4160 IteratorA++; 4161 IteratorB++; 4162 } // end of while loop 4163 }// end of check in case of equal sizes 4164 } 4165 return false; // if we reach this point, they are equal 4166 4166 }; 4167 4167 4168 4168 //bool operator < (KeySet SubgraphA, KeySet SubgraphB) 4169 4169 //{ 4170 // return KeyCompare(SubgraphA, SubgraphB);4170 // return KeyCompare(SubgraphA, SubgraphB); 4171 4171 //}; 4172 4172 … … 4180 4180 inline void InsertFragmentIntoGraph(ofstream *out, struct UniqueFragments *Fragment) 4181 4181 { 4182 GraphTestPair testGraphInsert;4183 4184 testGraphInsert = Fragment->Leaflet->insert(GraphPair (*Fragment->FragmentSet,pair<int,double>(Fragment->FragmentCounter,Fragment->TEFactor)));// store fragment number and current factor4185 if (testGraphInsert.second) {4186 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " successfully inserted." << endl;4187 Fragment->FragmentCounter++;4188 } else {4189 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;4190 ((*(testGraphInsert.first)).second).second += Fragment->TEFactor;// increase the "created" counter4191 *out << Verbose(2) << "New factor is " << ((*(testGraphInsert.first)).second).second << "." << endl;4192 }4182 GraphTestPair testGraphInsert; 4183 4184 testGraphInsert = Fragment->Leaflet->insert(GraphPair (*Fragment->FragmentSet,pair<int,double>(Fragment->FragmentCounter,Fragment->TEFactor))); // store fragment number and current factor 4185 if (testGraphInsert.second) { 4186 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " successfully inserted." << endl; 4187 Fragment->FragmentCounter++; 4188 } else { 4189 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl; 4190 ((*(testGraphInsert.first)).second).second += Fragment->TEFactor; // increase the "created" counter 4191 *out << Verbose(2) << "New factor is " << ((*(testGraphInsert.first)).second).second << "." << endl; 4192 } 4193 4193 }; 4194 4194 //void inline InsertIntoGraph(ofstream *out, KeyStack &stack, Graph &graph, int *counter, double factor) 4195 4195 //{ 4196 // // copy stack contents to set and call overloaded function again4197 // KeySet set;4198 // for(KeyStack::iterator runner = stack.begin(); runner != stack.begin(); runner++)4199 // set.insert((*runner));4200 // InsertIntoGraph(out, set, graph, counter, factor);4196 // // copy stack contents to set and call overloaded function again 4197 // KeySet set; 4198 // for(KeyStack::iterator runner = stack.begin(); runner != stack.begin(); runner++) 4199 // set.insert((*runner)); 4200 // InsertIntoGraph(out, set, graph, counter, factor); 4201 4201 //}; 4202 4202 … … 4209 4209 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter) 4210 4210 { 4211 GraphTestPair testGraphInsert;4212 4213 for(Graph::iterator runner = graph2.begin(); runner != graph2.end(); runner++) {4214 testGraphInsert = graph1.insert(GraphPair ((*runner).first,pair<int,double>((*counter)++,((*runner).second).second)));// store fragment number and current factor4215 if (testGraphInsert.second) {4216 *out << Verbose(2) << "KeySet " << (*counter)-1 << " successfully inserted." << endl;4217 } else {4218 *out << Verbose(2) << "KeySet " << (*counter)-1 << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;4219 ((*(testGraphInsert.first)).second).second += (*runner).second.second;4220 *out << Verbose(2) << "New factor is " << (*(testGraphInsert.first)).second.second << "." << endl;4221 }4222 }4211 GraphTestPair testGraphInsert; 4212 4213 for(Graph::iterator runner = graph2.begin(); runner != graph2.end(); runner++) { 4214 testGraphInsert = graph1.insert(GraphPair ((*runner).first,pair<int,double>((*counter)++,((*runner).second).second))); // store fragment number and current factor 4215 if (testGraphInsert.second) { 4216 *out << Verbose(2) << "KeySet " << (*counter)-1 << " successfully inserted." << endl; 4217 } else { 4218 *out << Verbose(2) << "KeySet " << (*counter)-1 << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl; 4219 ((*(testGraphInsert.first)).second).second += (*runner).second.second; 4220 *out << Verbose(2) << "New factor is " << (*(testGraphInsert.first)).second.second << "." << endl; 4221 } 4222 } 4223 4223 }; 4224 4224 … … 4227 4227 * -# constructs a complete keyset of the molecule 4228 4228 * -# In a loop over all possible roots from the given rootstack 4229 * -# increases order of root site4230 * -# calls PowerSetGenerator with this order, the complete keyset and the rootkeynr4231 * -# for all consecutive lower levels PowerSetGenerator is called with the suborder, the higher order keyset4229 * -# increases order of root site 4230 * -# calls PowerSetGenerator with this order, the complete keyset and the rootkeynr 4231 * -# for all consecutive lower levels PowerSetGenerator is called with the suborder, the higher order keyset 4232 4232 as the restricted one and each site in the set as the root) 4233 * -# these are merged into a fragment list of keysets4233 * -# these are merged into a fragment list of keysets 4234 4234 * -# All fragment lists (for all orders, i.e. from all destination fields) are merged into one list for return 4235 4235 * Important only is that we create all fragments, it is not important if we create them more than once … … 4243 4243 void molecule::FragmentBOSSANOVA(ofstream *out, Graph *&FragmentList, KeyStack &RootStack, int *MinimumRingSize) 4244 4244 { 4245 Graph ***FragmentLowerOrdersList = NULL;4246 int NumLevels, NumMolecules, TotalNumMolecules = 0, *NumMoleculesOfOrder = NULL;4247 int counter = 0, Order;4248 int UpgradeCount = RootStack.size();4249 KeyStack FragmentRootStack;4250 int RootKeyNr, RootNr;4251 struct UniqueFragments FragmentSearch;4252 4253 *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl;4254 4255 // FragmentLowerOrdersList is a 2D-array of pointer to MoleculeListClass objects, one dimension represents the ANOVA expansion of a single order (i.e. 5)4256 // with all needed lower orders that are subtracted, the other dimension is the BondOrder (i.e. from 1 to 5)4257 NumMoleculesOfOrder = (int *) Malloc(sizeof(int)*UpgradeCount, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder");4258 FragmentLowerOrdersList = (Graph ***) Malloc(sizeof(Graph **)*UpgradeCount, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList");4259 4260 // initialise the fragments structure4261 FragmentSearch.ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::PowerSetGenerator: *ShortestPathList");4262 FragmentSearch.FragmentCounter = 0;4263 FragmentSearch.FragmentSet = new KeySet;4264 FragmentSearch.Root = FindAtom(RootKeyNr);4265 for (int i=AtomCount;i--;) {4266 FragmentSearch.ShortestPathList[i] = -1;4267 }4268 4269 // Construct the complete KeySet which we need for topmost level only (but for all Roots)4270 atom *Walker = start;4271 KeySet CompleteMolecule;4272 while (Walker->next != end) {4273 Walker = Walker->next;4274 CompleteMolecule.insert(Walker->GetTrueFather()->nr);4275 }4276 4277 // 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, as4278 // 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),4279 // hence we have overall four 2th order levels for splitting. This also allows for putting all into a single array (FragmentLowerOrdersList[])4280 // 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)4281 RootNr = 0;// counts through the roots in RootStack4282 while ((RootNr < UpgradeCount) && (!RootStack.empty())) {4283 RootKeyNr = RootStack.front();4284 RootStack.pop_front();4285 Walker = FindAtom(RootKeyNr);4286 // check cyclic lengths4287 //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) {4288 //*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;4289 //} else4290 {4291 // increase adaptive order by one4292 Walker->GetTrueFather()->AdaptiveOrder++;4293 Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder;4294 4295 // initialise Order-dependent entries of UniqueFragments structure4296 FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList");4297 FragmentSearch.BondsPerSPCount = (int *) Malloc(sizeof(int)*Order, "molecule::PowerSetGenerator: *BondsPerSPCount");4298 for (int i=Order;i--;) {4299 FragmentSearch.BondsPerSPList[2*i] = new bond();// start node4300 FragmentSearch.BondsPerSPList[2*i+1] = new bond();// end node4301 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1];// intertwine these two4302 FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i];4303 FragmentSearch.BondsPerSPCount[i] = 0;4304 }4305 4306 // allocate memory for all lower level orders in this 1D-array of ptrs4307 NumLevels = 1 << (Order-1); // (int)pow(2,Order);4308 FragmentLowerOrdersList[RootNr] = (Graph **) Malloc(sizeof(Graph *)*NumLevels, "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]");4309 for (int i=0;i<NumLevels;i++)4310 FragmentLowerOrdersList[RootNr][i] = NULL;4311 4312 // create top order where nothing is reduced4313 *out << Verbose(0) << "==============================================================================================================" << endl;4314 *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << "4315 4316 // Create list of Graphs of current Bond Order (i.e. F_{ij})4317 FragmentLowerOrdersList[RootNr][0] =new Graph;4318 FragmentSearch.TEFactor = 1.;4319 FragmentSearch.Leaflet = FragmentLowerOrdersList[RootNr][0];// set to insertion graph4320 FragmentSearch.Root = Walker;4321 NumMoleculesOfOrder[RootNr] = PowerSetGenerator(out, Walker->AdaptiveOrder, FragmentSearch, CompleteMolecule);4322 *out << Verbose(1) << "Number of resulting KeySets is: " << NumMoleculesOfOrder[RootNr] << "." << endl;4323 if (NumMoleculesOfOrder[RootNr] != 0) {4324 NumMolecules = 0;4325 4326 // we don't have to dive into suborders! These keysets are all already created on lower orders!4327 // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed)4328 4329 // if ((NumLevels >> 1) > 0) {4330 // // create lower order fragments4331 // *out << Verbose(0) << "Creating list of unique fragments of lower Bond Order terms to be subtracted." << endl;4332 // Order = Walker->AdaptiveOrder;4333 // 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)4334 // // step down to next order at (virtual) boundary of powers of 2 in array4335 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order))4336 // Order--;4337 // *out << Verbose(0) << "Current Order is: " << Order << "." << endl;4338 // for (int SubOrder=Order-1;SubOrder>0;SubOrder--) {4339 // int dest = source + (1 << (Walker->AdaptiveOrder-(SubOrder+1)));4340 // *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl;4341 // *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl;4245 Graph ***FragmentLowerOrdersList = NULL; 4246 int NumLevels, NumMolecules, TotalNumMolecules = 0, *NumMoleculesOfOrder = NULL; 4247 int counter = 0, Order; 4248 int UpgradeCount = RootStack.size(); 4249 KeyStack FragmentRootStack; 4250 int RootKeyNr, RootNr; 4251 struct UniqueFragments FragmentSearch; 4252 4253 *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl; 4254 4255 // FragmentLowerOrdersList is a 2D-array of pointer to MoleculeListClass objects, one dimension represents the ANOVA expansion of a single order (i.e. 5) 4256 // with all needed lower orders that are subtracted, the other dimension is the BondOrder (i.e. from 1 to 5) 4257 NumMoleculesOfOrder = (int *) Malloc(sizeof(int)*UpgradeCount, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder"); 4258 FragmentLowerOrdersList = (Graph ***) Malloc(sizeof(Graph **)*UpgradeCount, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); 4259 4260 // initialise the fragments structure 4261 FragmentSearch.ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::PowerSetGenerator: *ShortestPathList"); 4262 FragmentSearch.FragmentCounter = 0; 4263 FragmentSearch.FragmentSet = new KeySet; 4264 FragmentSearch.Root = FindAtom(RootKeyNr); 4265 for (int i=AtomCount;i--;) { 4266 FragmentSearch.ShortestPathList[i] = -1; 4267 } 4268 4269 // Construct the complete KeySet which we need for topmost level only (but for all Roots) 4270 atom *Walker = start; 4271 KeySet CompleteMolecule; 4272 while (Walker->next != end) { 4273 Walker = Walker->next; 4274 CompleteMolecule.insert(Walker->GetTrueFather()->nr); 4275 } 4276 4277 // 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 4278 // 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), 4279 // hence we have overall four 2th order levels for splitting. This also allows for putting all into a single array (FragmentLowerOrdersList[]) 4280 // 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) 4281 RootNr = 0; // counts through the roots in RootStack 4282 while ((RootNr < UpgradeCount) && (!RootStack.empty())) { 4283 RootKeyNr = RootStack.front(); 4284 RootStack.pop_front(); 4285 Walker = FindAtom(RootKeyNr); 4286 // check cyclic lengths 4287 //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) { 4288 // *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; 4289 //} else 4290 { 4291 // increase adaptive order by one 4292 Walker->GetTrueFather()->AdaptiveOrder++; 4293 Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder; 4294 4295 // initialise Order-dependent entries of UniqueFragments structure 4296 FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList"); 4297 FragmentSearch.BondsPerSPCount = (int *) Malloc(sizeof(int)*Order, "molecule::PowerSetGenerator: *BondsPerSPCount"); 4298 for (int i=Order;i--;) { 4299 FragmentSearch.BondsPerSPList[2*i] = new bond(); // start node 4300 FragmentSearch.BondsPerSPList[2*i+1] = new bond(); // end node 4301 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1]; // intertwine these two 4302 FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i]; 4303 FragmentSearch.BondsPerSPCount[i] = 0; 4304 } 4305 4306 // allocate memory for all lower level orders in this 1D-array of ptrs 4307 NumLevels = 1 << (Order-1); // (int)pow(2,Order); 4308 FragmentLowerOrdersList[RootNr] = (Graph **) Malloc(sizeof(Graph *)*NumLevels, "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]"); 4309 for (int i=0;i<NumLevels;i++) 4310 FragmentLowerOrdersList[RootNr][i] = NULL; 4311 4312 // create top order where nothing is reduced 4313 *out << Verbose(0) << "==============================================================================================================" << endl; 4314 *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << " 4315 4316 // Create list of Graphs of current Bond Order (i.e. F_{ij}) 4317 FragmentLowerOrdersList[RootNr][0] = new Graph; 4318 FragmentSearch.TEFactor = 1.; 4319 FragmentSearch.Leaflet = FragmentLowerOrdersList[RootNr][0]; // set to insertion graph 4320 FragmentSearch.Root = Walker; 4321 NumMoleculesOfOrder[RootNr] = PowerSetGenerator(out, Walker->AdaptiveOrder, FragmentSearch, CompleteMolecule); 4322 *out << Verbose(1) << "Number of resulting KeySets is: " << NumMoleculesOfOrder[RootNr] << "." << endl; 4323 if (NumMoleculesOfOrder[RootNr] != 0) { 4324 NumMolecules = 0; 4325 4326 // we don't have to dive into suborders! These keysets are all already created on lower orders! 4327 // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed) 4328 4329 // if ((NumLevels >> 1) > 0) { 4330 // // create lower order fragments 4331 // *out << Verbose(0) << "Creating list of unique fragments of lower Bond Order terms to be subtracted." << endl; 4332 // Order = Walker->AdaptiveOrder; 4333 // 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) 4334 // // step down to next order at (virtual) boundary of powers of 2 in array 4335 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order)) 4336 // Order--; 4337 // *out << Verbose(0) << "Current Order is: " << Order << "." << endl; 4338 // for (int SubOrder=Order-1;SubOrder>0;SubOrder--) { 4339 // int dest = source + (1 << (Walker->AdaptiveOrder-(SubOrder+1))); 4340 // *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl; 4341 // *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl; 4342 4342 // 4343 // // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules4344 // //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl;4345 // //NumMolecules = 0;4346 // FragmentLowerOrdersList[RootNr][dest] = new Graph;4347 // for(Graph::iterator runner = (*FragmentLowerOrdersList[RootNr][source]).begin();runner != (*FragmentLowerOrdersList[RootNr][source]).end(); runner++) {4348 // for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) {4349 // Graph TempFragmentList;4350 // FragmentSearch.TEFactor = -(*runner).second.second;4351 // FragmentSearch.Leaflet = &TempFragmentList;// set to insertion graph4352 // FragmentSearch.Root = FindAtom(*sprinter);4353 // NumMoleculesOfOrder[RootNr] += PowerSetGenerator(out, SubOrder, FragmentSearch, (*runner).first);4354 // // insert new keysets FragmentList into FragmentLowerOrdersList[Walker->AdaptiveOrder-1][dest]4355 // *out << Verbose(1) << "Merging resulting key sets with those present in destination " << dest << "." << endl;4356 // InsertGraphIntoGraph(out, *FragmentLowerOrdersList[RootNr][dest], TempFragmentList, &NumMolecules);4357 // }4358 // }4359 // *out << Verbose(1) << "Number of resulting molecules for SubOrder " << SubOrder << " is: " << NumMolecules << "." << endl;4360 // }4361 // }4362 // }4363 } else {4364 Walker->GetTrueFather()->MaxOrder = true;4365 // *out << Verbose(1) << "Hence, we don't dive into SubOrders ... " << endl;4366 }4367 // now, we have completely filled each cell of FragmentLowerOrdersList[] for the current Walker->AdaptiveOrder4368 //NumMoleculesOfOrder[Walker->AdaptiveOrder-1] = NumMolecules;4369 TotalNumMolecules += NumMoleculesOfOrder[RootNr];4370 // *out << Verbose(1) << "Number of resulting molecules for Order " << (int)Walker->GetTrueFather()->AdaptiveOrder << " is: " << NumMoleculesOfOrder[RootNr] << "." << endl;4371 RootStack.push_back(RootKeyNr); // put back on stack4372 RootNr++;4373 4374 // free Order-dependent entries of UniqueFragments structure for next loop cycle4375 Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount");4376 for (int i=Order;i--;) {4377 delete(FragmentSearch.BondsPerSPList[2*i]);4378 delete(FragmentSearch.BondsPerSPList[2*i+1]);4379 }4380 Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList");4381 }4382 }4383 *out << Verbose(0) << "==============================================================================================================" << endl;4384 *out << Verbose(1) << "Total number of resulting molecules is: " << TotalNumMolecules << "." << endl;4385 *out << Verbose(0) << "==============================================================================================================" << endl;4386 4387 // cleanup FragmentSearch structure4388 Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList");4389 delete(FragmentSearch.FragmentSet);4390 4391 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein)4392 // 54332222111111114393 // 432211114394 // 32114395 // 214396 // 14397 4398 // Subsequently, we combine all into a single list (FragmentList)4399 4400 *out << Verbose(0) << "Combining the lists of all orders per order and finally into a single one." << endl;4401 if (FragmentList == NULL) {4402 FragmentList = new Graph;4403 counter = 0;4404 } else {4405 counter = FragmentList->size();4406 }4407 RootNr = 0;4408 while (!RootStack.empty()) {4409 RootKeyNr = RootStack.front();4410 RootStack.pop_front();4411 Walker = FindAtom(RootKeyNr);4412 NumLevels = 1 << (Walker->AdaptiveOrder - 1);4413 for(int i=0;i<NumLevels;i++) {4414 if (FragmentLowerOrdersList[RootNr][i] != NULL) {4415 InsertGraphIntoGraph(out, *FragmentList, (*FragmentLowerOrdersList[RootNr][i]), &counter);4416 delete(FragmentLowerOrdersList[RootNr][i]);4417 }4418 }4419 Free((void **)&FragmentLowerOrdersList[RootNr], "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]");4420 RootNr++;4421 }4422 Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList");4423 Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder");4424 4425 *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl;4343 // // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules 4344 // //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl; 4345 // //NumMolecules = 0; 4346 // FragmentLowerOrdersList[RootNr][dest] = new Graph; 4347 // for(Graph::iterator runner = (*FragmentLowerOrdersList[RootNr][source]).begin();runner != (*FragmentLowerOrdersList[RootNr][source]).end(); runner++) { 4348 // for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 4349 // Graph TempFragmentList; 4350 // FragmentSearch.TEFactor = -(*runner).second.second; 4351 // FragmentSearch.Leaflet = &TempFragmentList; // set to insertion graph 4352 // FragmentSearch.Root = FindAtom(*sprinter); 4353 // NumMoleculesOfOrder[RootNr] += PowerSetGenerator(out, SubOrder, FragmentSearch, (*runner).first); 4354 // // insert new keysets FragmentList into FragmentLowerOrdersList[Walker->AdaptiveOrder-1][dest] 4355 // *out << Verbose(1) << "Merging resulting key sets with those present in destination " << dest << "." << endl; 4356 // InsertGraphIntoGraph(out, *FragmentLowerOrdersList[RootNr][dest], TempFragmentList, &NumMolecules); 4357 // } 4358 // } 4359 // *out << Verbose(1) << "Number of resulting molecules for SubOrder " << SubOrder << " is: " << NumMolecules << "." << endl; 4360 // } 4361 // } 4362 // } 4363 } else { 4364 Walker->GetTrueFather()->MaxOrder = true; 4365 // *out << Verbose(1) << "Hence, we don't dive into SubOrders ... " << endl; 4366 } 4367 // now, we have completely filled each cell of FragmentLowerOrdersList[] for the current Walker->AdaptiveOrder 4368 //NumMoleculesOfOrder[Walker->AdaptiveOrder-1] = NumMolecules; 4369 TotalNumMolecules += NumMoleculesOfOrder[RootNr]; 4370 // *out << Verbose(1) << "Number of resulting molecules for Order " << (int)Walker->GetTrueFather()->AdaptiveOrder << " is: " << NumMoleculesOfOrder[RootNr] << "." << endl; 4371 RootStack.push_back(RootKeyNr); // put back on stack 4372 RootNr++; 4373 4374 // free Order-dependent entries of UniqueFragments structure for next loop cycle 4375 Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount"); 4376 for (int i=Order;i--;) { 4377 delete(FragmentSearch.BondsPerSPList[2*i]); 4378 delete(FragmentSearch.BondsPerSPList[2*i+1]); 4379 } 4380 Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList"); 4381 } 4382 } 4383 *out << Verbose(0) << "==============================================================================================================" << endl; 4384 *out << Verbose(1) << "Total number of resulting molecules is: " << TotalNumMolecules << "." << endl; 4385 *out << Verbose(0) << "==============================================================================================================" << endl; 4386 4387 // cleanup FragmentSearch structure 4388 Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList"); 4389 delete(FragmentSearch.FragmentSet); 4390 4391 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein) 4392 // 5433222211111111 4393 // 43221111 4394 // 3211 4395 // 21 4396 // 1 4397 4398 // Subsequently, we combine all into a single list (FragmentList) 4399 4400 *out << Verbose(0) << "Combining the lists of all orders per order and finally into a single one." << endl; 4401 if (FragmentList == NULL) { 4402 FragmentList = new Graph; 4403 counter = 0; 4404 } else { 4405 counter = FragmentList->size(); 4406 } 4407 RootNr = 0; 4408 while (!RootStack.empty()) { 4409 RootKeyNr = RootStack.front(); 4410 RootStack.pop_front(); 4411 Walker = FindAtom(RootKeyNr); 4412 NumLevels = 1 << (Walker->AdaptiveOrder - 1); 4413 for(int i=0;i<NumLevels;i++) { 4414 if (FragmentLowerOrdersList[RootNr][i] != NULL) { 4415 InsertGraphIntoGraph(out, *FragmentList, (*FragmentLowerOrdersList[RootNr][i]), &counter); 4416 delete(FragmentLowerOrdersList[RootNr][i]); 4417 } 4418 } 4419 Free((void **)&FragmentLowerOrdersList[RootNr], "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]"); 4420 RootNr++; 4421 } 4422 Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); 4423 Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder"); 4424 4425 *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl; 4426 4426 }; 4427 4427 … … 4433 4433 inline int CompareDoubles (const void * a, const void * b) 4434 4434 { 4435 if (*(double *)a > *(double *)b)4436 return -1;4437 else if (*(double *)a < *(double *)b)4438 return 1;4439 else4440 return 0;4435 if (*(double *)a > *(double *)b) 4436 return -1; 4437 else if (*(double *)a < *(double *)b) 4438 return 1; 4439 else 4440 return 0; 4441 4441 }; 4442 4442 … … 4449 4449 int * molecule::IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold) 4450 4450 { 4451 int flag;4452 double *Distances = NULL, *OtherDistances = NULL;4453 Vector CenterOfGravity, OtherCenterOfGravity;4454 size_t *PermMap = NULL, *OtherPermMap = NULL;4455 int *PermutationMap = NULL;4456 atom *Walker = NULL;4457 bool result = true; // status of comparison4458 4459 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl;4460 /// first count both their atoms and elements and update lists thereby ...4461 //*out << Verbose(0) << "Counting atoms, updating list" << endl;4462 CountAtoms(out);4463 OtherMolecule->CountAtoms(out);4464 CountElements();4465 OtherMolecule->CountElements();4466 4467 /// ... and compare:4468 /// -# AtomCount4469 if (result) {4470 if (AtomCount != OtherMolecule->AtomCount) {4471 *out << Verbose(4) << "AtomCounts don't match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl;4472 result = false;4473 } else *out << Verbose(4) << "AtomCounts match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl;4474 }4475 /// -# ElementCount4476 if (result) {4477 if (ElementCount != OtherMolecule->ElementCount) {4478 *out << Verbose(4) << "ElementCount don't match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;4479 result = false;4480 } else *out << Verbose(4) << "ElementCount match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;4481 }4482 /// -# ElementsInMolecule4483 if (result) {4484 for (flag=MAX_ELEMENTS;flag--;) {4485 //*out << Verbose(5) << "Element " <<flag << ": " << ElementsInMolecule[flag] << " <-> " << OtherMolecule->ElementsInMolecule[flag] << "." << endl;4486 if (ElementsInMolecule[flag] != OtherMolecule->ElementsInMolecule[flag])4487 break;4488 }4489 if (flag < MAX_ELEMENTS) {4490 *out << Verbose(4) << "ElementsInMolecule don't match." << endl;4491 result = false;4492 } else *out << Verbose(4) << "ElementsInMolecule match." << endl;4493 }4494 /// then determine and compare center of gravity for each molecule ...4495 if (result) {4496 *out << Verbose(5) << "Calculating Centers of Gravity" << endl;4497 DetermineCenter(CenterOfGravity);4498 OtherMolecule->DetermineCenter(OtherCenterOfGravity);4499 *out << Verbose(5) << "Center of Gravity: ";4500 CenterOfGravity.Output(out);4501 *out << endl << Verbose(5) << "Other Center of Gravity: ";4502 OtherCenterOfGravity.Output(out);4503 *out << endl;4504 if (CenterOfGravity.DistanceSquared(&OtherCenterOfGravity) > threshold*threshold) {4505 *out << Verbose(4) << "Centers of gravity don't match." << endl;4506 result = false;4507 }4508 }4509 4510 /// ... then make a list with the euclidian distance to this center for each atom of both molecules4511 if (result) {4512 *out << Verbose(5) << "Calculating distances" << endl;4513 Distances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: Distances");4514 OtherDistances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: OtherDistances");4515 Walker = start;4516 while (Walker->next != end) {4517 Walker = Walker->next;4518 Distances[Walker->nr] = CenterOfGravity.DistanceSquared(&Walker->x);4519 }4520 Walker = OtherMolecule->start;4521 while (Walker->next != OtherMolecule->end) {4522 Walker = Walker->next;4523 OtherDistances[Walker->nr] = OtherCenterOfGravity.DistanceSquared(&Walker->x);4524 }4525 4526 /// ... sort each list (using heapsort (o(N log N)) from GSL)4527 *out << Verbose(5) << "Sorting distances" << endl;4528 PermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermMap");4529 OtherPermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *OtherPermMap");4530 gsl_heapsort_index (PermMap, Distances, AtomCount, sizeof(double), CompareDoubles);4531 gsl_heapsort_index (OtherPermMap, OtherDistances, AtomCount, sizeof(double), CompareDoubles);4532 PermutationMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermutationMap");4533 *out << Verbose(5) << "Combining Permutation Maps" << endl;4534 for(int i=AtomCount;i--;)4535 PermutationMap[PermMap[i]] = (int) OtherPermMap[i];4536 4537 /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all4538 *out << Verbose(4) << "Comparing distances" << endl;4539 flag = 0;4540 for (int i=0;i<AtomCount;i++) {4541 *out << Verbose(5) << "Distances squared: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " <<threshold << endl;4542 if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) > threshold*threshold)4543 flag = 1;4544 }4545 Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap");4546 Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap");4547 4548 /// free memory4549 Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances");4550 Free((void **)&OtherDistances, "molecule::IsEqualToWithinThreshold: OtherDistances");4551 if (flag) { // if not equal4552 Free((void **)&PermutationMap, "molecule::IsEqualToWithinThreshold: *PermutationMap");4553 result = false;4554 }4555 }4556 /// return pointer to map if all distances were below \a threshold4557 *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl;4558 if (result) {4559 *out << Verbose(3) << "Result: Equal." << endl;4560 return PermutationMap;4561 } else {4562 *out << Verbose(3) << "Result: Not equal." << endl;4563 return NULL;4564 }4451 int flag; 4452 double *Distances = NULL, *OtherDistances = NULL; 4453 Vector CenterOfGravity, OtherCenterOfGravity; 4454 size_t *PermMap = NULL, *OtherPermMap = NULL; 4455 int *PermutationMap = NULL; 4456 atom *Walker = NULL; 4457 bool result = true; // status of comparison 4458 4459 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 4460 /// first count both their atoms and elements and update lists thereby ... 4461 //*out << Verbose(0) << "Counting atoms, updating list" << endl; 4462 CountAtoms(out); 4463 OtherMolecule->CountAtoms(out); 4464 CountElements(); 4465 OtherMolecule->CountElements(); 4466 4467 /// ... and compare: 4468 /// -# AtomCount 4469 if (result) { 4470 if (AtomCount != OtherMolecule->AtomCount) { 4471 *out << Verbose(4) << "AtomCounts don't match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl; 4472 result = false; 4473 } else *out << Verbose(4) << "AtomCounts match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl; 4474 } 4475 /// -# ElementCount 4476 if (result) { 4477 if (ElementCount != OtherMolecule->ElementCount) { 4478 *out << Verbose(4) << "ElementCount don't match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl; 4479 result = false; 4480 } else *out << Verbose(4) << "ElementCount match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl; 4481 } 4482 /// -# ElementsInMolecule 4483 if (result) { 4484 for (flag=MAX_ELEMENTS;flag--;) { 4485 //*out << Verbose(5) << "Element " << flag << ": " << ElementsInMolecule[flag] << " <-> " << OtherMolecule->ElementsInMolecule[flag] << "." << endl; 4486 if (ElementsInMolecule[flag] != OtherMolecule->ElementsInMolecule[flag]) 4487 break; 4488 } 4489 if (flag < MAX_ELEMENTS) { 4490 *out << Verbose(4) << "ElementsInMolecule don't match." << endl; 4491 result = false; 4492 } else *out << Verbose(4) << "ElementsInMolecule match." << endl; 4493 } 4494 /// then determine and compare center of gravity for each molecule ... 4495 if (result) { 4496 *out << Verbose(5) << "Calculating Centers of Gravity" << endl; 4497 DetermineCenter(CenterOfGravity); 4498 OtherMolecule->DetermineCenter(OtherCenterOfGravity); 4499 *out << Verbose(5) << "Center of Gravity: "; 4500 CenterOfGravity.Output(out); 4501 *out << endl << Verbose(5) << "Other Center of Gravity: "; 4502 OtherCenterOfGravity.Output(out); 4503 *out << endl; 4504 if (CenterOfGravity.DistanceSquared(&OtherCenterOfGravity) > threshold*threshold) { 4505 *out << Verbose(4) << "Centers of gravity don't match." << endl; 4506 result = false; 4507 } 4508 } 4509 4510 /// ... then make a list with the euclidian distance to this center for each atom of both molecules 4511 if (result) { 4512 *out << Verbose(5) << "Calculating distances" << endl; 4513 Distances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: Distances"); 4514 OtherDistances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: OtherDistances"); 4515 Walker = start; 4516 while (Walker->next != end) { 4517 Walker = Walker->next; 4518 Distances[Walker->nr] = CenterOfGravity.DistanceSquared(&Walker->x); 4519 } 4520 Walker = OtherMolecule->start; 4521 while (Walker->next != OtherMolecule->end) { 4522 Walker = Walker->next; 4523 OtherDistances[Walker->nr] = OtherCenterOfGravity.DistanceSquared(&Walker->x); 4524 } 4525 4526 /// ... sort each list (using heapsort (o(N log N)) from GSL) 4527 *out << Verbose(5) << "Sorting distances" << endl; 4528 PermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermMap"); 4529 OtherPermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *OtherPermMap"); 4530 gsl_heapsort_index (PermMap, Distances, AtomCount, sizeof(double), CompareDoubles); 4531 gsl_heapsort_index (OtherPermMap, OtherDistances, AtomCount, sizeof(double), CompareDoubles); 4532 PermutationMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermutationMap"); 4533 *out << Verbose(5) << "Combining Permutation Maps" << endl; 4534 for(int i=AtomCount;i--;) 4535 PermutationMap[PermMap[i]] = (int) OtherPermMap[i]; 4536 4537 /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all 4538 *out << Verbose(4) << "Comparing distances" << endl; 4539 flag = 0; 4540 for (int i=0;i<AtomCount;i++) { 4541 *out << Verbose(5) << "Distances squared: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " << threshold << endl; 4542 if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) > threshold*threshold) 4543 flag = 1; 4544 } 4545 Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap"); 4546 Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap"); 4547 4548 /// free memory 4549 Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances"); 4550 Free((void **)&OtherDistances, "molecule::IsEqualToWithinThreshold: OtherDistances"); 4551 if (flag) { // if not equal 4552 Free((void **)&PermutationMap, "molecule::IsEqualToWithinThreshold: *PermutationMap"); 4553 result = false; 4554 } 4555 } 4556 /// return pointer to map if all distances were below \a threshold 4557 *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl; 4558 if (result) { 4559 *out << Verbose(3) << "Result: Equal." << endl; 4560 return PermutationMap; 4561 } else { 4562 *out << Verbose(3) << "Result: Not equal." << endl; 4563 return NULL; 4564 } 4565 4565 }; 4566 4566 … … 4574 4574 int * molecule::GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule) 4575 4575 { 4576 atom *Walker = NULL, *OtherWalker = NULL;4577 *out << Verbose(3) << "Begin of GetFatherAtomicMap." << endl;4578 int *AtomicMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::GetAtomicMap: *AtomicMap");//Calloc4579 for (int i=AtomCount;i--;)4580 AtomicMap[i] = -1;4581 if (OtherMolecule == this) {// same molecule4582 for (int i=AtomCount;i--;) // no need as -1 means already that there is trivial correspondence4583 AtomicMap[i] = i;4584 *out << Verbose(4) << "Map is trivial." << endl;4585 } else {4586 *out << Verbose(4) << "Map is ";4587 Walker = start;4588 while (Walker->next != end) {4589 Walker = Walker->next;4590 if (Walker->father == NULL) {4591 AtomicMap[Walker->nr] = -2;4592 } else {4593 OtherWalker = OtherMolecule->start;4594 while (OtherWalker->next != OtherMolecule->end) {4595 OtherWalker = OtherWalker->next;4596 //for (int i=0;i<AtomCount;i++) { // search atom4597 //for (int j=0;j<OtherMolecule->AtomCount;j++) {4598 //*out << Verbose(4) << "Comparing father " << Walker->father << " with the other one " << OtherWalker->father << "." << endl;4599 if (Walker->father == OtherWalker)4600 AtomicMap[Walker->nr] = OtherWalker->nr;4601 }4602 }4603 *out << AtomicMap[Walker->nr] << "\t";4604 }4605 *out << endl;4606 }4607 *out << Verbose(3) << "End of GetFatherAtomicMap." << endl;4608 return AtomicMap;4576 atom *Walker = NULL, *OtherWalker = NULL; 4577 *out << Verbose(3) << "Begin of GetFatherAtomicMap." << endl; 4578 int *AtomicMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::GetAtomicMap: *AtomicMap"); //Calloc 4579 for (int i=AtomCount;i--;) 4580 AtomicMap[i] = -1; 4581 if (OtherMolecule == this) { // same molecule 4582 for (int i=AtomCount;i--;) // no need as -1 means already that there is trivial correspondence 4583 AtomicMap[i] = i; 4584 *out << Verbose(4) << "Map is trivial." << endl; 4585 } else { 4586 *out << Verbose(4) << "Map is "; 4587 Walker = start; 4588 while (Walker->next != end) { 4589 Walker = Walker->next; 4590 if (Walker->father == NULL) { 4591 AtomicMap[Walker->nr] = -2; 4592 } else { 4593 OtherWalker = OtherMolecule->start; 4594 while (OtherWalker->next != OtherMolecule->end) { 4595 OtherWalker = OtherWalker->next; 4596 //for (int i=0;i<AtomCount;i++) { // search atom 4597 //for (int j=0;j<OtherMolecule->AtomCount;j++) { 4598 //*out << Verbose(4) << "Comparing father " << Walker->father << " with the other one " << OtherWalker->father << "." << endl; 4599 if (Walker->father == OtherWalker) 4600 AtomicMap[Walker->nr] = OtherWalker->nr; 4601 } 4602 } 4603 *out << AtomicMap[Walker->nr] << "\t"; 4604 } 4605 *out << endl; 4606 } 4607 *out << Verbose(3) << "End of GetFatherAtomicMap." << endl; 4608 return AtomicMap; 4609 4609 }; 4610 4610 … … 4620 4620 bool molecule::OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output) 4621 4621 { 4622 double temperature;4623 atom *Walker = NULL;4624 // test stream4625 if (output == NULL)4626 return false;4627 else4628 *output << "# Step Temperature [K] Temperature [a.u.]" << endl;4629 for (int step=startstep;step < endstep; step++) { // loop over all time steps4630 temperature = 0.;4631 Walker = start;4632 while (Walker->next != end) {4633 Walker = Walker->next;4634 for (int i=NDIM;i--;)4635 temperature += Walker->type->mass * Trajectories[Walker].U.at(step).x[i]* Trajectories[Walker].U.at(step).x[i];4636 }4637 *output << step << "\t" << temperature*AtomicEnergyToKelvin << "\t" << temperature << endl;4638 }4639 return true;4640 }; 4622 double temperature; 4623 atom *Walker = NULL; 4624 // test stream 4625 if (output == NULL) 4626 return false; 4627 else 4628 *output << "# Step Temperature [K] Temperature [a.u.]" << endl; 4629 for (int step=startstep;step < endstep; step++) { // loop over all time steps 4630 temperature = 0.; 4631 Walker = start; 4632 while (Walker->next != end) { 4633 Walker = Walker->next; 4634 for (int i=NDIM;i--;) 4635 temperature += Walker->type->mass * Trajectories[Walker].U.at(step).x[i]* Trajectories[Walker].U.at(step).x[i]; 4636 } 4637 *output << step << "\t" << temperature*AtomicEnergyToKelvin << "\t" << temperature << endl; 4638 } 4639 return true; 4640 };
Note:
See TracChangeset
for help on using the changeset viewer.
